Decompiled source of MoreItemStyles v1.0.0

plugins\MoreItemStyles.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using MoreItemStyles.Styles;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MoreItemStyles")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+32f7c319a7ffe3594e4defa6e09134e2909f921b")]
[assembly: AssemblyProduct("MoreItemStyles")]
[assembly: AssemblyTitle("MoreItemStyles")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MoreItemStyles
{
	public static class ItemStyles
	{
		private static readonly List<Registration> Entries = new List<Registration>();

		internal static IReadOnlyList<Registration> All => Entries;

		public static void Register(StyledItem item, ConfigFile config)
		{
			if (item == null)
			{
				throw new ArgumentNullException("item");
			}
			if (config == null)
			{
				throw new ArgumentNullException("config");
			}
			if (item.Styles.Count == 0)
			{
				Plugin.Log.LogWarning((object)("\"" + item.PrefabName + "\" was registered with no styles; ignoring it."));
				return;
			}
			Registration registration = Entries.FirstOrDefault((Registration e) => e.Item.PrefabName == item.PrefabName);
			if (registration != null)
			{
				Plugin.Log.LogWarning((object)("\"" + item.PrefabName + "\" is already styled by " + registration.Owner + "; ignoring the second registration."));
			}
			else
			{
				Registration registration2 = new Registration(item, config);
				Entries.Add(registration2);
				Plugin.Log.LogInfo((object)$"Registered \"{item.PrefabName}\" with {item.Styles.Count} style(s) from {registration2.Owner}.");
				Plugin.RequestRebuild();
			}
		}

		public static void Unregister(StyledItem item)
		{
			if (item != null)
			{
				Registration registration = Entries.FirstOrDefault((Registration e) => e.Item == item);
				if (registration != null)
				{
					registration.Release();
					Entries.Remove(registration);
					StyleCatalog.Restore(item.PrefabName);
					Plugin.RequestRebuild();
				}
			}
		}

		internal static void UnregisterAll()
		{
			foreach (Registration entry in Entries)
			{
				entry.Release();
			}
			Entries.Clear();
		}
	}
	internal sealed class Registration
	{
		private readonly ConfigEntry<Color>[] _colors;

		public StyledItem Item { get; }

		public string Owner { get; }

		public Registration(StyledItem item, ConfigFile config)
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Item = item;
			Owner = Path.GetFileNameWithoutExtension(config.ConfigFilePath);
			_colors = new ConfigEntry<Color>[item.Styles.Count];
			for (int i = 0; i < item.Styles.Count; i++)
			{
				StyleOption styleOption = item.Styles[i];
				_colors[i] = config.Bind<Color>(item.DisplayName, styleOption.Name, styleOption.DefaultColor, "The base colour for the " + styleOption.Name + " " + item.DisplayName + ". This is the colour BEFORE the game lights it, so in daylight the item looks considerably brighter than the swatch here - the shipped values look almost black and are correct. Pick darker than the result you want, or just drag the sliders and watch the item change. The tint multiplies the item's own texture, so its shading and detail survive and strong colours come out muted. Alpha is ignored.");
				_colors[i].SettingChanged += OnColorChanged;
			}
		}

		public Color GetTarget(int index)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			if (index < 0 || index >= _colors.Length)
			{
				return Color.white;
			}
			return _colors[index].Value;
		}

		public void Release()
		{
			ConfigEntry<Color>[] colors = _colors;
			foreach (ConfigEntry<Color> val in colors)
			{
				if (val != null)
				{
					val.SettingChanged -= OnColorChanged;
				}
			}
		}

		private static void OnColorChanged(object sender, EventArgs e)
		{
			Plugin.RequestRebuild();
		}
	}
	[BepInPlugin("wheeze.valheim.moreitemstyles", "More Item Styles", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "wheeze.valheim.moreitemstyles";

		public const string PluginName = "More Item Styles";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private static Plugin _instance;

		private Harmony _harmony;

		private float _rebuildAt = -1f;

		private const float RebuildDelay = 0.12f;

		private void Awake()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_instance = this;
			StyleSettings.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("wheeze.valheim.moreitemstyles");
			_harmony.PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)(string.Format("{0} {1} loaded; {2} method(s) patched. ", "More Item Styles", "1.0.0", _harmony.GetPatchedMethods().Count()) + "Waiting for add-ons to register items."));
		}

		internal static void RequestRebuild()
		{
			if ((Object)(object)_instance != (Object)null)
			{
				_instance._rebuildAt = Time.realtimeSinceStartup + 0.12f;
			}
		}

		private void Update()
		{
			if (!(_rebuildAt < 0f) && !(Time.realtimeSinceStartup < _rebuildAt))
			{
				_rebuildAt = -1f;
				StyleCatalog.Rebuild();
				VisualRefresher.RefreshAll();
			}
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			ItemStyles.UnregisterAll();
			StyleCatalog.Reset();
			StyleTint.Reset();
			VisualRefresher.RefreshAll();
			_instance = null;
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"More Item Styles unloaded.");
			}
		}
	}
	public sealed class StyleOption
	{
		public string Name { get; }

		public Color DefaultColor { get; }

		internal StyleOption(string name, Color defaultColor)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Name = name;
			DefaultColor = defaultColor;
		}
	}
	public sealed class StyledItem
	{
		private readonly List<StyleOption> _styles = new List<StyleOption>();

		public string PrefabName { get; }

		public string DisplayName { get; }

		public IReadOnlyList<StyleOption> Styles => _styles;

		public StyledItem(string prefabName, string displayName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				throw new ArgumentException("A styled item needs a prefab name.", "prefabName");
			}
			PrefabName = prefabName;
			DisplayName = (string.IsNullOrEmpty(displayName) ? prefabName : displayName);
		}

		public StyledItem AddStyle(string name, Color defaultColor)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name))
			{
				throw new ArgumentException("A style needs a name.", "name");
			}
			_styles.Add(new StyleOption(name, defaultColor));
			return this;
		}

		public StyledItem AddStyle(string name, string defaultColorHex)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			return AddStyle(name, ColorSpec.Hex(defaultColorHex));
		}
	}
}
namespace MoreItemStyles.Styles
{
	internal static class ColorSpec
	{
		public static Color ToMultiplier(Color target, Color meanAlbedo)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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_0022: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			return new Color(Ratio(target.r, meanAlbedo.r), Ratio(target.g, meanAlbedo.g), Ratio(target.b, meanAlbedo.b), 1f);
		}

		private static float Ratio(float target, float mean)
		{
			return Mathf.Clamp(target / Mathf.Max(mean, 0.02f), 0f, 16f);
		}

		public static Color Hex(string rrggbb)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			string s = rrggbb.TrimStart(new char[1] { '#' });
			uint num = uint.Parse(s, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
			return new Color((float)((num >> 16) & 0xFF) / 255f, (float)((num >> 8) & 0xFF) / 255f, (float)(num & 0xFF) / 255f, 1f);
		}
	}
	internal static class IconTinter
	{
		private static readonly List<Object> Generated = new List<Object>();

		public static Sprite Tint(Sprite source, Color tint, string name)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			//IL_007e: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.texture == (Object)null)
			{
				return source;
			}
			Rect textureRect = source.textureRect;
			int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			if (num <= 0 || num2 <= 0)
			{
				return source;
			}
			Color[] array = ReadPixels(source.texture, textureRect, num, num2, name);
			if (array == null)
			{
				return source;
			}
			for (int i = 0; i < array.Length; i++)
			{
				Color val = array[i];
				array[i] = new Color(Mathf.Clamp01(val.r * tint.r), Mathf.Clamp01(val.g * tint.g), Mathf.Clamp01(val.b * tint.b), val.a);
			}
			Texture2D val2 = new Texture2D(num, num2, (TextureFormat)4, false)
			{
				name = name + "_tex",
				filterMode = ((Texture)source.texture).filterMode,
				wrapMode = (TextureWrapMode)1,
				hideFlags = (HideFlags)61
			};
			val2.SetPixels(array);
			val2.Apply(false, false);
			Rect rect = source.rect;
			Vector2 val3;
			if (((Rect)(ref rect)).size.x > 0f)
			{
				rect = source.rect;
				if (((Rect)(ref rect)).size.y > 0f)
				{
					float x = source.pivot.x;
					rect = source.rect;
					float num3 = x / ((Rect)(ref rect)).width;
					float y = source.pivot.y;
					rect = source.rect;
					val3 = new Vector2(num3, y / ((Rect)(ref rect)).height);
					goto IL_0191;
				}
			}
			val3 = new Vector2(0.5f, 0.5f);
			goto IL_0191;
			IL_0191:
			Vector2 val4 = val3;
			Sprite val5 = Sprite.Create(val2, new Rect(0f, 0f, (float)num, (float)num2), val4, source.pixelsPerUnit, 0u, (SpriteMeshType)0);
			((Object)val5).name = name;
			((Object)val5).hideFlags = (HideFlags)61;
			Generated.Add((Object)(object)val2);
			Generated.Add((Object)(object)val5);
			return val5;
		}

		public static bool TryAverageColor(Texture texture, bool weightByAlpha, out Color average)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_0061: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: 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)
			average = Color.white;
			if ((Object)(object)texture == (Object)null)
			{
				return false;
			}
			RenderTexture temporary = RenderTexture.GetTemporary(64, 64, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			Texture2D val = null;
			try
			{
				Graphics.Blit(texture, temporary);
				RenderTexture.active = temporary;
				val = new Texture2D(64, 64, (TextureFormat)4, false)
				{
					hideFlags = (HideFlags)61
				};
				val.ReadPixels(new Rect(0f, 0f, 64f, 64f), 0, 0, false);
				val.Apply(false, false);
				Color[] pixels = val.GetPixels();
				float num = 0f;
				float num2 = 0f;
				float num3 = 0f;
				float num4 = 0f;
				Color[] array = pixels;
				foreach (Color val2 in array)
				{
					float num5 = (weightByAlpha ? val2.a : 1f);
					num += val2.r * num5;
					num2 += val2.g * num5;
					num3 += val2.b * num5;
					num4 += num5;
				}
				if (num4 <= 0f)
				{
					return false;
				}
				average = new Color(num / num4, num2 / num4, num3 / num4, 1f);
				return true;
			}
			catch (Exception)
			{
				return false;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}

		public static bool TryAverageSpriteColor(Sprite sprite, out Color average)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			average = Color.grey;
			if ((Object)(object)sprite == (Object)null || (Object)(object)sprite.texture == (Object)null)
			{
				return false;
			}
			Rect textureRect = sprite.textureRect;
			int num = Mathf.RoundToInt(((Rect)(ref textureRect)).width);
			int num2 = Mathf.RoundToInt(((Rect)(ref textureRect)).height);
			if (num <= 0 || num2 <= 0)
			{
				return false;
			}
			Color[] array = ReadPixels(sprite.texture, textureRect, num, num2, ((Object)sprite).name);
			if (array == null)
			{
				return false;
			}
			float num3 = 0f;
			float num4 = 0f;
			float num5 = 0f;
			float num6 = 0f;
			Color[] array2 = array;
			foreach (Color val in array2)
			{
				num3 += val.r * val.a;
				num4 += val.g * val.a;
				num5 += val.b * val.a;
				num6 += val.a;
			}
			if (num6 <= 0f)
			{
				return false;
			}
			average = new Color(num3 / num6, num4 / num6, num5 / num6, 1f);
			return true;
		}

		public static void ReleaseAll()
		{
			foreach (Object item in Generated)
			{
				if (item != (Object)null)
				{
					Object.DestroyImmediate(item);
				}
			}
			Generated.Clear();
		}

		private static Color[] ReadPixels(Texture2D texture, Rect rect, int width, int height, string name)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			if (((Texture)texture).isReadable)
			{
				return texture.GetPixels(Mathf.RoundToInt(((Rect)(ref rect)).x), Mathf.RoundToInt(((Rect)(ref rect)).y), width, height);
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2);
			RenderTexture active = RenderTexture.active;
			Texture2D val = null;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				val = new Texture2D(width, height, (TextureFormat)4, false)
				{
					hideFlags = (HideFlags)61
				};
				val.ReadPixels(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, (float)width, (float)height), 0, 0, false);
				val.Apply(false, false);
				return val.GetPixels();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read icon pixels for " + name + ": " + ex.Message));
				return null;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				if ((Object)(object)val != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val);
				}
			}
		}
	}
	internal static class StyleCatalog
	{
		private sealed class Entry
		{
			public Registration Reg;

			public GameObject Prefab;

			public int PrefabHash;

			public SharedData Shared;

			public Sprite[] VanillaIcons;

			public int VanillaVariants;

			public Color[] Tints;

			public Color MaterialMean;

			public Color IconMean;
		}

		private struct VanillaIcons
		{
			public Sprite[] Icons;

			public int Variants;
		}

		private static readonly Dictionary<int, Entry> ByHash = new Dictionary<int, Entry>();

		private static readonly Dictionary<SharedData, Entry> BySharedData = new Dictionary<SharedData, Entry>();

		private static readonly Dictionary<SharedData, VanillaIcons> Vanilla = new Dictionary<SharedData, VanillaIcons>();

		private static readonly HashSet<string> Skipped = new HashSet<string>();

		private static ObjectDB _installedInto;

		public static bool IsStyled(int prefabHash)
		{
			return ByHash.ContainsKey(prefabHash);
		}

		public static bool TryGetTint(int prefabHash, int variant, out Color tint)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			tint = Color.white;
			if (variant <= 0 || !ByHash.TryGetValue(prefabHash, out var value))
			{
				return false;
			}
			if (value.Tints == null || variant >= value.Tints.Length)
			{
				return false;
			}
			tint = value.Tints[variant];
			return true;
		}

		public static bool TryGetHash(SharedData shared, out int prefabHash)
		{
			prefabHash = 0;
			if (shared == null || !BySharedData.TryGetValue(shared, out var value))
			{
				return false;
			}
			prefabHash = value.PrefabHash;
			return true;
		}

		public static void Install(ObjectDB db)
		{
			if ((Object)(object)db == (Object)null || db.m_items == null || db.m_items.Count == 0)
			{
				return;
			}
			_installedInto = db;
			ByHash.Clear();
			BySharedData.Clear();
			IconTinter.ReleaseAll();
			bool value = StyleSettings.Enabled.Value;
			int num = 0;
			foreach (Registration item in ItemStyles.All)
			{
				Entry entry = Resolve(db, item);
				if (entry != null)
				{
					if (!value)
					{
						Restore(entry);
						continue;
					}
					Apply(entry);
					ByHash[entry.PrefabHash] = entry;
					BySharedData[entry.Shared] = entry;
					num++;
				}
			}
			if (value)
			{
				Plugin.Log.LogInfo((object)$"Installed styles on {num} of {ItemStyles.All.Count} registered item(s).");
				if (num < ItemStyles.All.Count && (Object)(object)ZNetScene.instance != (Object)null)
				{
					Plugin.Log.LogWarning((object)$"{ItemStyles.All.Count - num} styled item(s) could not be set up; see the lines above.");
				}
			}
			else
			{
				Plugin.Log.LogInfo((object)"Styles are disabled; every item left as vanilla.");
			}
		}

		public static void Rebuild()
		{
			ObjectDB val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance : _installedInto);
			if (!((Object)(object)val == (Object)null))
			{
				Install(val);
				StyleTint.ReapplyLive();
			}
		}

		public static void Reset()
		{
			foreach (Entry item in ByHash.Values.ToList())
			{
				Restore(item);
			}
			ByHash.Clear();
			BySharedData.Clear();
			Vanilla.Clear();
			Skipped.Clear();
			IconTinter.ReleaseAll();
			_installedInto = null;
		}

		public static void Restore(string prefabName)
		{
			int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName);
			if (ByHash.TryGetValue(stableHashCode, out var value))
			{
				Restore(value);
				ByHash.Remove(stableHashCode);
				BySharedData.Remove(value.Shared);
			}
		}

		private static Entry Resolve(ObjectDB db, Registration reg)
		{
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			GameObject itemPrefab = db.GetItemPrefab(reg.Item.PrefabName);
			if ((Object)(object)itemPrefab == (Object)null)
			{
				Plugin.Log.LogInfo((object)("Item prefab \"" + reg.Item.PrefabName + "\" is not in this ObjectDB."));
				return null;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
			{
				Plugin.Log.LogWarning((object)("Prefab \"" + reg.Item.PrefabName + "\" has no usable ItemDrop; skipping."));
				return null;
			}
			SharedData shared = component.m_itemData.m_shared;
			if (!Vanilla.TryGetValue(shared, out var value))
			{
				value = new VanillaIcons
				{
					Icons = (Sprite[])(((object)shared.m_icons) ?? ((object)new Sprite[0])),
					Variants = shared.m_variants
				};
				Vanilla[shared] = value;
			}
			if (value.Variants > 1)
			{
				if (Skipped.Add(reg.Item.PrefabName))
				{
					Plugin.Log.LogWarning((object)$"\"{reg.Item.PrefabName}\" already has {value.Variants} styles; leaving it alone.");
				}
				return null;
			}
			if (value.Icons.Length == 0 || (Object)(object)value.Icons[0] == (Object)null)
			{
				Plugin.Log.LogWarning((object)("\"" + reg.Item.PrefabName + "\" has no icon to tint; skipping."));
				return null;
			}
			return new Entry
			{
				Reg = reg,
				Prefab = itemPrefab,
				PrefabHash = StringExtensionMethods.GetStableHashCode(reg.Item.PrefabName),
				Shared = shared,
				VanillaIcons = value.Icons,
				VanillaVariants = value.Variants,
				MaterialMean = MeasureMaterial(itemPrefab, reg.Item.PrefabName),
				IconMean = MeasureIcon(value.Icons[0], reg.Item.PrefabName)
			};
		}

		private static Color MeasureMaterial(GameObject prefab, string prefabName)
		{
			//IL_004b: 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)
			Texture val = StyleTint.FindAlbedo(prefab);
			if ((Object)(object)val != (Object)null && IconTinter.TryAverageColor(val, weightByAlpha: false, out var average))
			{
				return average;
			}
			Plugin.Log.LogWarning((object)("Could not measure the albedo of \"" + prefabName + "\"; its styles may come out too bright or too dark. Falling back to mid grey."));
			return new Color(0.5f, 0.5f, 0.5f, 1f);
		}

		private static Color MeasureIcon(Sprite icon, string prefabName)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			if (IconTinter.TryAverageSpriteColor(icon, out var average))
			{
				return average;
			}
			Plugin.Log.LogWarning((object)("Could not measure the icon of \"" + prefabName + "\"; falling back to mid grey."));
			return new Color(0.5f, 0.5f, 0.5f, 1f);
		}

		private static void Apply(Entry entry)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			int num = entry.Reg.Item.Styles.Count + 1;
			Sprite[] array = (Sprite[])(object)new Sprite[num];
			Color[] array2 = (Color[])(object)new Color[num];
			array[0] = entry.VanillaIcons[0];
			array2[0] = Color.white;
			for (int i = 0; i < entry.Reg.Item.Styles.Count; i++)
			{
				StyleOption styleOption = entry.Reg.Item.Styles[i];
				Color target = entry.Reg.GetTarget(i);
				array2[i + 1] = ColorSpec.ToMultiplier(target, entry.MaterialMean);
				Color tint = ColorSpec.ToMultiplier(target, entry.IconMean);
				array[i + 1] = IconTinter.Tint(array[0], tint, entry.Reg.Item.PrefabName + "_" + styleOption.Name);
			}
			entry.Tints = array2;
			entry.Shared.m_icons = array;
			entry.Shared.m_variants = num;
			if (StyleSettings.LogStyleVisuals.Value)
			{
				StyleTint.LogPrefabMaterials(entry.Prefab, entry.Reg.Item.PrefabName);
			}
		}

		private static void Restore(Entry entry)
		{
			entry.Shared.m_icons = entry.VanillaIcons;
			entry.Shared.m_variants = entry.VanillaVariants;
		}
	}
	internal static class StyleSettings
	{
		private const string GeneralSection = "General";

		private const string DiagnosticsSection = "Diagnostics";

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<bool> LogStyleVisuals { get; private set; }

		public static void Bind(ConfigFile config)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Master switch for every item any add-on has registered. Turning this off leaves them exactly as vanilla has them. Items already crafted in a style keep their stored style and show it again when this is turned back on.");
			LogStyleVisuals = config.Bind<bool>("Diagnostics", "Log style visuals", false, new ConfigDescription("Log every model this mod tints, with its renderers, shaders and the colour applied. Use this when a style looks wrong: the log names the shader, which tells you whether it honours the _Color property at all, and reports the item's measured albedo - the number a new item's colours have to be chosen against.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					IsAdvanced = true
				}
			}));
			Enabled.SettingChanged += OnChanged;
		}

		private static void OnChanged(object sender, EventArgs e)
		{
			Plugin.RequestRebuild();
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? IsAdvanced;
	}
	internal static class StyleTint
	{
		private sealed class StyledInstance : MonoBehaviour
		{
			internal static readonly List<StyledInstance> All = new List<StyledInstance>();

			private readonly List<Renderer> _tinted = new List<Renderer>();

			private readonly List<Material[]> _originals = new List<Material[]>();

			private readonly List<Material[]> _copies = new List<Material[]>();

			private Color _tint = Color.white;

			private bool _logged;

			public void Apply(Color tint)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				_tint = tint;
				if (_copies.Count == 0)
				{
					Clone();
				}
				Refresh();
			}

			public void Refresh()
			{
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				bool flag = false;
				for (int i = 0; i < _copies.Count; i++)
				{
					Material[] array = _copies[i];
					Material[] array2 = _originals[i];
					for (int j = 0; j < array.Length; j++)
					{
						if (!((Object)(object)array[j] == (Object)null) && !((Object)(object)array2[j] == (Object)null))
						{
							Color color = array2[j].GetColor(ShaderProps._Color);
							Color val = _tint * color;
							val.a = color.a;
							array[j].SetColor(ShaderProps._Color, val);
							flag = true;
						}
					}
				}
				if (StyleSettings.LogStyleVisuals.Value && !_logged)
				{
					_logged = true;
					Plugin.Log.LogInfo((object)($"tinted {((Object)this).name}: {_tinted.Count} renderer(s) tinted, tint {Describe(_tint)}" + (flag ? "" : "; WARNING nothing exposed _Color, so the tint will not show")));
				}
			}

			private void Clone()
			{
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Expected O, but got Unknown
				List<Renderer> list = new List<Renderer>();
				((Component)this).GetComponentsInChildren<Renderer>(true, list);
				foreach (Renderer item in list)
				{
					Material[] sharedMaterials = item.sharedMaterials;
					Material[] array = (Material[])(object)new Material[sharedMaterials.Length];
					bool flag = false;
					for (int i = 0; i < sharedMaterials.Length; i++)
					{
						if (!((Object)(object)sharedMaterials[i] == (Object)null) && sharedMaterials[i].HasProperty(ShaderProps._Color))
						{
							array[i] = new Material(sharedMaterials[i])
							{
								name = ((Object)sharedMaterials[i]).name + " (styled)"
							};
							flag = true;
						}
					}
					if (flag)
					{
						Material[] array2 = (Material[])(object)new Material[sharedMaterials.Length];
						for (int j = 0; j < sharedMaterials.Length; j++)
						{
							array2[j] = (((Object)(object)array[j] != (Object)null) ? array[j] : sharedMaterials[j]);
						}
						_tinted.Add(item);
						_originals.Add(sharedMaterials);
						_copies.Add(array);
						item.sharedMaterials = array2;
					}
				}
				All.Add(this);
			}

			internal static void RestoreAll()
			{
				StyledInstance[] array = All.ToArray();
				foreach (StyledInstance styledInstance in array)
				{
					if ((Object)(object)styledInstance != (Object)null)
					{
						Object.Destroy((Object)(object)styledInstance);
					}
				}
				All.Clear();
			}

			private void OnDestroy()
			{
				All.Remove(this);
				for (int i = 0; i < _copies.Count; i++)
				{
					if ((Object)(object)_tinted[i] != (Object)null)
					{
						_tinted[i].sharedMaterials = _originals[i];
					}
					Material[] array = _copies[i];
					foreach (Material val in array)
					{
						if ((Object)(object)val != (Object)null)
						{
							Object.Destroy((Object)(object)val);
						}
					}
				}
				_copies.Clear();
				_originals.Clear();
				_tinted.Clear();
			}
		}

		private static readonly List<Renderer> RendererBuffer = new List<Renderer>();

		public static void Apply(GameObject instance, int prefabHash, int variant)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)instance == (Object)null) && StyleCatalog.TryGetTint(prefabHash, variant, out var tint))
			{
				StyledInstance styledInstance = instance.GetComponent<StyledInstance>() ?? instance.AddComponent<StyledInstance>();
				styledInstance.Apply(tint);
			}
		}

		public static void Apply(IEnumerable<GameObject> instances, int prefabHash, int variant)
		{
			if (instances == null)
			{
				return;
			}
			foreach (GameObject instance in instances)
			{
				Apply(instance, prefabHash, variant);
			}
		}

		public static void ReapplyLive()
		{
			foreach (StyledInstance item in StyledInstance.All)
			{
				item.Refresh();
			}
		}

		public static void Reset()
		{
			StyledInstance.RestoreAll();
		}

		public static Texture FindAlbedo(GameObject prefab)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			if ((Object)(object)prefab == (Object)null)
			{
				return null;
			}
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (!((Object)val).name.StartsWith("attach"))
				{
					continue;
				}
				((Component)val).GetComponentsInChildren<Renderer>(true, RendererBuffer);
				foreach (Renderer item2 in RendererBuffer)
				{
					Material val2 = (((Object)(object)item2 != (Object)null) ? item2.sharedMaterial : null);
					if ((Object)(object)val2 != (Object)null && val2.HasProperty(ShaderProps._Color) && (Object)(object)val2.mainTexture != (Object)null)
					{
						return val2.mainTexture;
					}
				}
			}
			return null;
		}

		private static string Describe(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			return $"({c.r:0.##}, {c.g:0.##}, {c.b:0.##})";
		}

		public static void LogPrefabMaterials(GameObject prefab, string label)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (!((Object)val).name.StartsWith("attach"))
				{
					continue;
				}
				((Component)val).GetComponentsInChildren<Renderer>(true, RendererBuffer);
				foreach (Renderer item2 in RendererBuffer)
				{
					Material val2 = (((Object)(object)item2 != (Object)null) ? item2.sharedMaterial : null);
					if ((Object)(object)val2 == (Object)null)
					{
						Plugin.Log.LogInfo((object)(label + "/" + ((Object)val).name + ": " + ((item2 != null) ? ((Object)item2).name : null) + " has no material."));
						continue;
					}
					bool flag = val2.HasProperty(ShaderProps._Color);
					string text = (((Object)(object)val2.shader != (Object)null) ? ((Object)val2.shader).name : "<none>");
					string text2 = (flag ? ("_Color = " + Describe(val2.GetColor(ShaderProps._Color))) : "NO _Color property - this renderer cannot be tinted");
					Color average;
					string text3 = (IconTinter.TryAverageColor(val2.mainTexture, weightByAlpha: false, out average) ? (", mean albedo " + Describe(average)) : "");
					Plugin.Log.LogInfo((object)(label + "/" + ((Object)val).name + ": " + ((Object)item2).name + " [" + ((object)item2).GetType().Name + "] shader \"" + text + "\", " + text2 + text3));
					Plugin.Log.LogInfo((object)("    colour properties: " + ColourProperties(val2)));
				}
			}
		}

		private static string ColourProperties(Material material)
		{
			//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)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Invalid comparison between Unknown and I4
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			Shader shader = material.shader;
			if ((Object)(object)shader == (Object)null)
			{
				return "<no shader>";
			}
			StringBuilder stringBuilder = new StringBuilder();
			int propertyCount = shader.GetPropertyCount();
			for (int i = 0; i < propertyCount; i++)
			{
				ShaderPropertyType propertyType = shader.GetPropertyType(i);
				if ((int)propertyType == 0 || (int)propertyType == 1)
				{
					if (stringBuilder.Length > 0)
					{
						stringBuilder.Append(", ");
					}
					string propertyName = shader.GetPropertyName(i);
					stringBuilder.Append(((int)propertyType == 0) ? (propertyName + "=" + Describe(material.GetColor(propertyName))) : propertyName);
				}
			}
			if (stringBuilder.Length <= 0)
			{
				return "<none>";
			}
			return stringBuilder.ToString();
		}
	}
	internal static class VisualRefresher
	{
		private const int Invalid = int.MinValue;

		public static void RefreshAll()
		{
			VisEquipment[] array;
			try
			{
				array = Object.FindObjectsByType<VisEquipment>((FindObjectsSortMode)0);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not enumerate equipment visuals to refresh: " + ex.Message));
				return;
			}
			VisEquipment[] array2 = array;
			foreach (VisEquipment val in array2)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.m_currentShoulderItemVariant = int.MinValue;
					val.m_currentLeftItemVariant = int.MinValue;
					val.m_currentLeftBackItemVariant = int.MinValue;
				}
			}
		}
	}
}
namespace MoreItemStyles.Patches
{
	[HarmonyPatch(typeof(ItemDrop), "Start")]
	internal static class ItemDropStartPatch
	{
		private static void Postfix(ItemDrop __instance)
		{
			ItemData val = (((Object)(object)__instance != (Object)null) ? __instance.m_itemData : null);
			if (val != null && val.m_variant > 0 && StyleCatalog.TryGetHash(val.m_shared, out var prefabHash))
			{
				StyleTint.Apply(((Component)__instance).gameObject, prefabHash, val.m_variant);
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand), "SetVisualItem")]
	internal static class ItemStandSetVisualItemPatch
	{
		private static void Postfix(ItemStand __instance, int itemHash, int variant)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance.m_visualItem == (Object)null) && variant > 0 && StyleCatalog.IsStyled(itemHash))
			{
				StyleTint.Apply(__instance.m_visualItem, itemHash, variant);
			}
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	internal static class ObjectDBAwakePatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			StyleCatalog.Install(__instance);
		}
	}
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	internal static class ObjectDBCopyOtherDBPatch
	{
		private static void Postfix(ObjectDB __instance)
		{
			StyleCatalog.Install(__instance);
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "AttachArmor")]
	internal static class VisEquipmentAttachArmorPatch
	{
		private static void Postfix(int itemHash, int variant, List<GameObject> __result)
		{
			if (__result != null && variant > 0 && StyleCatalog.IsStyled(itemHash))
			{
				StyleTint.Apply((IEnumerable<GameObject>)__result, itemHash, variant);
			}
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "AttachItem")]
	internal static class VisEquipmentAttachItemPatch
	{
		private static void Postfix(int itemHash, int variant, GameObject __result)
		{
			if (!((Object)(object)__result == (Object)null) && variant > 0 && StyleCatalog.IsStyled(itemHash))
			{
				StyleTint.Apply(__result, itemHash, variant);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}