plugins/MikuFufu.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("MikuFufu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MikuFufu")]
[assembly: AssemblyTitle("MikuFufu")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	public sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		private readonly string _assemblyName;

		public string AssemblyName => _assemblyName;

		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
			_assemblyName = assemblyName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	public sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte value)
		{
			Flag = value;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
	public sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int version)
		{
			Version = version;
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace BepInEx
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
	public sealed class BepInAutoPluginAttribute : Attribute
	{
		private string _guid;

		private string _name;

		private string _version;

		public string GUID
		{
			get
			{
				return _guid;
			}
			set
			{
				_guid = value;
			}
		}

		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}

		public string Version
		{
			get
			{
				return _version;
			}
			set
			{
				_version = value;
			}
		}

		public BepInAutoPluginAttribute(string guid = null, string name = null, string version = null)
		{
			_guid = guid;
			_name = name;
			_version = version;
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
	public sealed class PatcherAutoPluginAttribute : Attribute
	{
		private string _guid;

		private string _name;

		private string _version;

		public string GUID
		{
			get
			{
				return _guid;
			}
			set
			{
				_guid = value;
			}
		}

		public string Name
		{
			get
			{
				return _name;
			}
			set
			{
				_name = value;
			}
		}

		public string Version
		{
			get
			{
				return _version;
			}
			set
			{
				_version = value;
			}
		}

		public PatcherAutoPluginAttribute(string guid = null, string name = null, string version = null)
		{
			_guid = guid;
			_name = name;
			_version = version;
		}
	}
}
namespace MikuFufu
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.github.Thanks.MikuFufu", "MikuFufu", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string LegacyPluginId = "com.github.FelineEntity.MikuBongFix";

		private const string BundleFileName = "fufupeak";

		private const string ModelAssetPath = "assets/mikufumo/fufu.fbx";

		private const string MaterialAssetPath = "assets/mikufumo/materials/miku.mat";

		private const string IconTextureAssetPath = "assets/mikufumo/miku_icon.png";

		private const string MainTextureAssetPath = "assets/mikufumo/miku.png";

		private const string AltTextureAssetPath = "assets/mikufumo/miku1.png";

		private const string ConfigSection = "Main";

		private const float InventoryIconVisibleScale = 0.76f;

		private const float WorldMinScaleMultiplier = 0.7f;

		private const float WorldMaxScaleMultiplier = 1.1f;

		private const float BackpackMinScaleMultiplier = 0.2f;

		private const float BackpackMaxScaleMultiplier = 1f;

		private const float DefaultWorldScaleMultiplier = 0.9f;

		private const float DefaultBackpackScaleMultiplier = 0.4f;

		private static readonly string[] PreferredTextureProps = new string[2] { "_BaseMap", "_MainTex" };

		private static readonly string[] PrefabNameHints = new string[4] { "mikufumo", "miku", "fumo", "fufu" };

		private static readonly string[] MaterialNameHints = new string[4] { "m_mikufumo", "mikufumo", "miku", "fufu" };

		private static readonly string[] IconTextureNameHints = new string[4] { "miku_icon", "icon", "miku", "fufu" };

		private static readonly string[] MainTextureNameHints = new string[4] { "miku", "mikufumo", "albedo", "fufu" };

		private static readonly string[] AltTextureNameHints = new string[4] { "miku1", "fufu1", "alt", "detail" };

		private static readonly Color MikuStyleTint = new Color(0.98f, 1f, 1f, 1f);

		private static ConfigEntry<bool> _modEnabled;

		private static ConfigEntry<float> _worldScaleMultiplier;

		private static ConfigEntry<float> _backpackScaleMultiplier;

		private static ManualLogSource _log;

		private static AssetBundle _bundle;

		private static GameObject _mochiPrefab;

		private static Material _mochiMaterial;

		private static Material _runtimeMikuMaterial;

		private static Texture2D _mochiTexture;

		private static Texture2D _mikuMainTexture;

		private static Texture2D _mikuAltTexture;

		public const string Name = "MikuFufu";

		public const string Id = "com.github.Thanks.MikuFufu";

		public const string Version = "1.0.0";

		internal static Harmony Harmony = new Harmony("com.github.Thanks.MikuFufu");

		internal static ManualLogSource Log
		{
			get
			{
				return _log;
			}
			private set
			{
				_log = value;
			}
		}

		internal static AssetBundle Bundle
		{
			get
			{
				return _bundle;
			}
			private set
			{
				_bundle = value;
			}
		}

		internal static GameObject MochiPrefab
		{
			get
			{
				return _mochiPrefab;
			}
			private set
			{
				_mochiPrefab = value;
			}
		}

		internal static Material MochiMaterial
		{
			get
			{
				return _mochiMaterial;
			}
			private set
			{
				_mochiMaterial = value;
			}
		}

		internal static Material RuntimeMikuMaterial
		{
			get
			{
				return _runtimeMikuMaterial;
			}
			private set
			{
				_runtimeMikuMaterial = value;
			}
		}

		internal static Texture2D MochiTexture
		{
			get
			{
				return _mochiTexture;
			}
			private set
			{
				_mochiTexture = value;
			}
		}

		internal static Texture2D MikuMainTexture
		{
			get
			{
				return _mikuMainTexture;
			}
			private set
			{
				_mikuMainTexture = value;
			}
		}

		internal static Texture2D MikuAltTexture
		{
			get
			{
				return _mikuAltTexture;
			}
			private set
			{
				_mikuAltTexture = value;
			}
		}

		internal static bool ModEnabled
		{
			get
			{
				if (_modEnabled != null)
				{
					return _modEnabled.Value;
				}
				return true;
			}
		}

		internal static bool KeepOriginalRendererRefs => true;

		internal static bool EnableVisibilityGuard => true;

		internal static float WorldScaleMultiplier
		{
			get
			{
				if (_worldScaleMultiplier != null)
				{
					return Mathf.Clamp(_worldScaleMultiplier.Value, 0.7f, 1.1f);
				}
				return 0.9f;
			}
		}

		internal static float BackpackScaleMultiplier
		{
			get
			{
				if (_backpackScaleMultiplier != null)
				{
					return Mathf.Clamp(_backpackScaleMultiplier.Value, 0.2f, 1f);
				}
				return 0.4f;
			}
		}

		internal static string directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			MigrateLegacyConfigIfNeeded();
			InitializeConfig();
			LoadAssets();
			try
			{
				Harmony.PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to apply Harmony patches: " + ex));
			}
		}

		private void MigrateLegacyConfigIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				string text = Path.Combine(Paths.ConfigPath, "com.github.FelineEntity.MikuBongFix.cfg");
				if (!string.IsNullOrEmpty(configFilePath) && !string.IsNullOrEmpty(text) && !File.Exists(configFilePath) && File.Exists(text))
				{
					File.Copy(text, configFilePath, overwrite: false);
					((BaseUnityPlugin)this).Config.Reload();
					Log.LogInfo((object)("Migrated legacy config to: " + configFilePath));
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to migrate legacy config file: " + ex.Message));
			}
		}

		private void InitializeConfig()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			_modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Enable Fufu Replacement", true, new ConfigDescription("Master switch for the mod. When disabled, the original BingBong visuals, name, icon, and colliders are restored.", (AcceptableValueBase)null, Array.Empty<object>()));
			_worldScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Fufu Size In World", 0.9f, new ConfigDescription("Scale multiplier for Fufu while held or lying in the world.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.7f, 1.1f), Array.Empty<object>()));
			_backpackScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Fufu Size In Backpack", 0.4f, new ConfigDescription("Scale multiplier for the Fufu replacement while stored in the backpack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
		}

		private void LoadAssets()
		{
			string text = Path.Combine(directory, "fufupeak");
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				Log.LogError((object)("Failed to load AssetBundle: " + text));
				return;
			}
			MochiPrefab = LoadBundleAssetWithFallback<GameObject>("assets/mikufumo/fufu.fbx", PrefabNameHints);
			MochiMaterial = LoadBundleAssetWithFallback<Material>("assets/mikufumo/materials/miku.mat", MaterialNameHints);
			Texture2D val = LoadBundleAssetWithFallback<Texture2D>("assets/mikufumo/miku_icon.png", IconTextureNameHints);
			Texture2D val2 = CreateReadableTexture(val) ?? val;
			MochiTexture = CreatePaddedIconTexture(val2, 0.76f) ?? val2 ?? val;
			MikuMainTexture = LoadBundleAssetWithFallback<Texture2D>("assets/mikufumo/miku.png", MainTextureNameHints);
			MikuAltTexture = LoadBundleAssetWithFallback<Texture2D>("assets/mikufumo/miku1.png", AltTextureNameHints);
			if ((Object)(object)MochiPrefab == (Object)null)
			{
				Log.LogError((object)"Failed to load replacement model from asset bundle.");
				return;
			}
			ConfigureMochiMaterial();
			RuntimeMikuMaterial = (((Object)(object)MochiMaterial == (Object)null) ? CreateRuntimeMikuMaterial(MikuMainTexture) : null);
			if ((Object)(object)RuntimeMikuMaterial == (Object)null)
			{
				Log.LogInfo((object)"Using bundled material from fufupeak.");
			}
			if ((Object)(object)MochiTexture == (Object)null)
			{
				Log.LogWarning((object)"Failed to load replacement icon texture.");
			}
			if ((Object)(object)MikuMainTexture == (Object)null)
			{
				Log.LogWarning((object)"Failed to load replacement main texture.");
			}
			if ((Object)(object)MikuAltTexture == (Object)null)
			{
				Log.LogWarning((object)"Failed to load replacement secondary texture.");
			}
			LogBundleResourceStatus();
		}

		internal static void VerboseLog(string message)
		{
		}

		private static T LoadBundleAssetWithFallback<T>(string preferredPath, params string[] nameHints) where T : Object
		{
			if ((Object)(object)Bundle == (Object)null)
			{
				return default(T);
			}
			if (!string.IsNullOrEmpty(preferredPath))
			{
				T val = Bundle.LoadAsset<T>(preferredPath);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			string[] allAssetNames = Bundle.GetAllAssetNames();
			if (allAssetNames != null)
			{
				foreach (string text in allAssetNames)
				{
					if (AssetNameLooksRelevant(text, preferredPath, nameHints))
					{
						T val2 = Bundle.LoadAsset<T>(text);
						if ((Object)(object)val2 != (Object)null)
						{
							Log.LogWarning((object)("Loaded fallback " + typeof(T).Name + " from bundle path: " + text));
							return val2;
						}
					}
				}
			}
			T[] array = Bundle.LoadAllAssets<T>();
			if (array == null || array.Length == 0)
			{
				Log.LogWarning((object)("No " + typeof(T).Name + " assets found in bundle for requested path: " + preferredPath));
				return default(T);
			}
			T val3 = FindAssetByObjectName(array, preferredPath, nameHints);
			if ((Object)(object)val3 != (Object)null)
			{
				Log.LogWarning((object)("Loaded fallback " + typeof(T).Name + " by object name: " + ((Object)val3).name));
				return val3;
			}
			if (array.Length == 1)
			{
				Log.LogWarning((object)("Loaded only available " + typeof(T).Name + " asset as fallback: " + ((Object)array[0]).name));
				return array[0];
			}
			Log.LogWarning((object)("Unable to identify " + typeof(T).Name + " for requested path '" + preferredPath + "'. Candidates: " + string.Join(", ", Array.ConvertAll(array, (T asset) => (!((Object)(object)asset != (Object)null)) ? "<null>" : ((Object)asset).name))));
			return default(T);
		}

		private static T FindAssetByObjectName<T>(T[] assets, string preferredPath, string[] nameHints) where T : Object
		{
			string needle = (string.IsNullOrEmpty(preferredPath) ? string.Empty : Path.GetFileNameWithoutExtension(preferredPath));
			foreach (T val in assets)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string value = ((Object)val).name ?? string.Empty;
					if (NameMatches(value, needle) || NameMatchesAnyHint(value, nameHints))
					{
						return val;
					}
				}
			}
			return default(T);
		}

		private static bool AssetNameLooksRelevant(string assetName, string preferredPath, string[] nameHints)
		{
			if (string.IsNullOrEmpty(assetName))
			{
				return false;
			}
			if (!string.IsNullOrEmpty(preferredPath))
			{
				if (assetName.Equals(preferredPath, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				string fileName = Path.GetFileName(preferredPath);
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(preferredPath);
				if (!string.IsNullOrEmpty(fileName) && assetName.EndsWith(fileName, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				if (NameMatches(assetName, fileNameWithoutExtension))
				{
					return true;
				}
			}
			return NameMatchesAnyHint(assetName, nameHints);
		}

		private static bool NameMatchesAnyHint(string value, string[] hints)
		{
			if (string.IsNullOrEmpty(value) || hints == null)
			{
				return false;
			}
			for (int i = 0; i < hints.Length; i++)
			{
				if (NameMatches(value, hints[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static bool NameMatches(string value, string needle)
		{
			if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(needle))
			{
				return false;
			}
			return value.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static void ConfigureMochiMaterial()
		{
			if (!((Object)(object)MochiMaterial == (Object)null) && ((Object)(object)MochiMaterial.shader == (Object)null || !MochiMaterial.shader.isSupported))
			{
				Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard");
				if ((Object)(object)val != (Object)null)
				{
					MochiMaterial.shader = val;
					Log.LogWarning((object)("Bundled material shader was unavailable. Switched to fallback shader: " + ((Object)val).name));
				}
			}
		}

		private static void LogBundleResourceStatus()
		{
			Log.LogInfo((object)("fufupeak resource check: prefab=" + ((Object)(object)MochiPrefab != (Object)null) + ", material=" + ((Object)(object)MochiMaterial != (Object)null) + ", icon=" + ((Object)(object)MochiTexture != (Object)null) + ", mainTex=" + ((Object)(object)MikuMainTexture != (Object)null) + ", altTex=" + ((Object)(object)MikuAltTexture != (Object)null)));
		}

		private static bool TryAssignTexture(Material material, string propertyName, Texture texture)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null || (Object)(object)texture == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName))
			{
				return false;
			}
			try
			{
				material.SetTexture(propertyName, texture);
				material.SetTextureScale(propertyName, Vector2.one);
				material.SetTextureOffset(propertyName, Vector2.zero);
				return true;
			}
			catch (Exception ex)
			{
				VerboseLog("Skip texture assignment on material '" + ((Object)material).name + "', property '" + propertyName + "': " + ex.Message);
				return false;
			}
		}

		private static void TryAssignTexture(Material material, string[] propertyNames, Texture texture)
		{
			if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null) && propertyNames != null)
			{
				for (int i = 0; i < propertyNames.Length; i++)
				{
					TryAssignTexture(material, propertyNames[i], texture);
				}
			}
		}

		private static void ApplyTextureSet(Material material, Texture2D albedo)
		{
			if (!((Object)(object)material == (Object)null))
			{
				TryAssignTexture(material, PreferredTextureProps, (Texture)(object)albedo);
				ApplyMikuColorStyle(material);
			}
		}

		private static void ApplyMikuColorStyle(Material material)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Tint"))
				{
					material.SetColor("_Tint", MikuStyleTint);
				}
				if (material.HasProperty("_BaseColor"))
				{
					material.SetColor("_BaseColor", MikuStyleTint);
				}
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", MikuStyleTint);
				}
				if (material.HasProperty("_Smoothness"))
				{
					material.SetFloat("_Smoothness", 0.1f);
				}
				if (material.HasProperty("_Glossiness"))
				{
					material.SetFloat("_Glossiness", 0.1f);
				}
				if (material.HasProperty("_Metallic"))
				{
					material.SetFloat("_Metallic", 0f);
				}
				if (material.HasProperty("_BumpScale"))
				{
					material.SetFloat("_BumpScale", 0f);
				}
				if (material.HasProperty("_OcclusionStrength"))
				{
					material.SetFloat("_OcclusionStrength", 0f);
				}
				if (material.HasProperty("_SpecularHighlights"))
				{
					material.SetFloat("_SpecularHighlights", 0f);
				}
				if (material.HasProperty("_EnvironmentReflections"))
				{
					material.SetFloat("_EnvironmentReflections", 0f);
				}
				if (material.HasProperty("_EmissionColor"))
				{
					material.SetColor("_EmissionColor", Color.black);
					material.DisableKeyword("_EMISSION");
				}
				material.DisableKeyword("_NORMALMAP");
				material.DisableKeyword("_METALLICSPECGLOSSMAP");
				material.DisableKeyword("_OCCLUSIONMAP");
			}
		}

		private static Texture2D CreateReadableTexture(Texture2D source)
		{
			//IL_000f: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			try
			{
				source.GetPixel(0, 0);
				return source;
			}
			catch
			{
			}
			RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)source, temporary);
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, true, false)
				{
					name = ((Object)source).name + "_Readable"
				};
				val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0);
				val.Apply(true, false);
				return val;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		private static Texture2D CreatePaddedIconTexture(Texture2D source, float visibleScale)
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			visibleScale = Mathf.Clamp(visibleScale, 0.45f, 1f);
			int num = Mathf.Max(1, ((Texture)source).width);
			int num2 = Mathf.Max(1, ((Texture)source).height);
			int num3 = Mathf.Max(1, Mathf.RoundToInt((float)num * visibleScale));
			int num4 = Mathf.Max(1, Mathf.RoundToInt((float)num2 * visibleScale));
			int num5 = (num - num3) / 2;
			int num6 = (num2 - num4) / 2;
			Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false, false)
			{
				name = ((Object)source).name + "_Inventory"
			};
			Color32[] pixels = (Color32[])(object)new Color32[num * num2];
			val.SetPixels32(pixels);
			Color[] array = (Color[])(object)new Color[num3 * num4];
			for (int i = 0; i < num4; i++)
			{
				float num7 = ((num4 == 1) ? 0.5f : ((float)i / (float)(num4 - 1)));
				for (int j = 0; j < num3; j++)
				{
					float num8 = ((num3 == 1) ? 0.5f : ((float)j / (float)(num3 - 1)));
					array[i * num3 + j] = source.GetPixelBilinear(num8, num7);
				}
			}
			val.SetPixels(num5, num6, num3, num4, array);
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			val.Apply(false, false);
			return val;
		}

		private static Material CreateRuntimeMikuMaterial(Texture2D texture)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			Shader val = Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("W/Peak_Standard") ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Texture");
			if ((Object)(object)val == (Object)null)
			{
				Log.LogError((object)"Failed to create runtime material because no compatible shader was found.");
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "Fufu_RuntimeMaterial",
				renderQueue = 2000,
				color = Color.white
			};
			if ((Object)(object)texture != (Object)null)
			{
				TryAssignTexture(val2, "_BaseMap", (Texture)(object)texture);
				TryAssignTexture(val2, "_MainTex", (Texture)(object)texture);
			}
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 0f);
			}
			if (val2.HasProperty("_Blend"))
			{
				val2.SetFloat("_Blend", 0f);
			}
			if (val2.HasProperty("_ZWrite"))
			{
				val2.SetFloat("_ZWrite", 1f);
			}
			if (val2.HasProperty("_Cull"))
			{
				val2.SetFloat("_Cull", 0f);
			}
			val2.SetOverrideTag("RenderType", "Opaque");
			val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val2.EnableKeyword("_SURFACE_TYPE_OPAQUE");
			ApplyMikuColorStyle(val2);
			return val2;
		}
	}
	public class MikuMarker : MonoBehaviour
	{
	}
	public class MikuSuppressedRendererSource : MonoBehaviour
	{
	}
	public class MikuPoseTemplate : MonoBehaviour
	{
		private Vector3 _authoredLocalPosition = Vector3.zero;

		private Quaternion _authoredLocalRotation = Quaternion.identity;

		private Vector3 _authoredLocalScale = Vector3.one;

		public Vector3 AuthoredLocalPosition => _authoredLocalPosition;

		public Quaternion AuthoredLocalRotation => _authoredLocalRotation;

		public Vector3 AuthoredLocalScale => _authoredLocalScale;

		public void Initialize(Vector3 localPosition, Quaternion localRotation, Vector3 localScale)
		{
			//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)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_001c: 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)
			_authoredLocalPosition = localPosition;
			_authoredLocalRotation = localRotation;
			_authoredLocalScale = ((localScale == Vector3.zero) ? Vector3.one : localScale);
		}
	}
	public class MikuDeformGuard : MonoBehaviour
	{
		private const float SqueezeDuration = 0.78f;

		private const float SqueezeCompressPhase = 0.42f;

		private Transform[] _allTransforms = Array.Empty<Transform>();

		private Vector3[] _initialChildScales = Array.Empty<Vector3>();

		private Vector3 _rootLocalPosition;

		private Quaternion _rootLocalRotation;

		private Vector3 _rootLocalScale;

		private Item _boundItem;

		private bool _wasUsing;

		private float _squeezeElapsed = 0.78f;

		public void Initialize(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale)
		{
			//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)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			_rootLocalPosition = rootLocalPosition;
			_rootLocalRotation = rootLocalRotation;
			_rootLocalScale = rootLocalScale;
			_wasUsing = false;
			_squeezeElapsed = 0.78f;
			Capture();
		}

		public void Bind(Item item)
		{
			_boundItem = item;
		}

		public void SetRootTarget(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale)
		{
			//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)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			_rootLocalPosition = rootLocalPosition;
			_rootLocalRotation = rootLocalRotation;
			_rootLocalScale = rootLocalScale;
		}

		private bool IsHeldAndUsing()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if ((Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1)
			{
				if (!_boundItem.isUsingPrimary)
				{
					return _boundItem.isUsingSecondary;
				}
				return true;
			}
			return false;
		}

		private void UpdateSingleSqueezeState()
		{
			bool flag = IsHeldAndUsing();
			if (flag && !_wasUsing)
			{
				_squeezeElapsed = 0f;
			}
			_wasUsing = flag;
			if (_squeezeElapsed < 0.78f)
			{
				_squeezeElapsed += Time.deltaTime;
			}
		}

		private float EvaluateSingleSqueezeWeight()
		{
			if (_squeezeElapsed >= 0.78f)
			{
				return 0f;
			}
			float num = Mathf.Clamp01(_squeezeElapsed / 0.78f);
			if (num <= 0.42f)
			{
				return Mathf.SmoothStep(0f, 1f, num / 0.42f);
			}
			float num2 = (num - 0.42f) / 0.58000004f;
			return Mathf.SmoothStep(1f, 0f, Mathf.Clamp01(num2));
		}

		private Vector3 GetDesiredRootScale(float squeezeWeight)
		{
			//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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (squeezeWeight <= 0.0005f)
			{
				return _rootLocalScale;
			}
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(1f - 0.14f * squeezeWeight, 1f + 0.11f * squeezeWeight, 1f - 0.14f * squeezeWeight);
			return Vector3.Scale(_rootLocalScale, val);
		}

		public void Capture()
		{
			//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)
			_allTransforms = ((Component)this).GetComponentsInChildren<Transform>(true);
			_initialChildScales = (Vector3[])(object)new Vector3[_allTransforms.Length];
			for (int i = 0; i < _allTransforms.Length; i++)
			{
				_initialChildScales[i] = _allTransforms[i].localScale;
			}
		}

		private void LateUpdate()
		{
			//IL_0027: 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_0050: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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)
			//IL_0069: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			if (_allTransforms.Length == 0 || _allTransforms.Length != _initialChildScales.Length)
			{
				Capture();
			}
			if (((Component)this).transform.localPosition != _rootLocalPosition)
			{
				((Component)this).transform.localPosition = _rootLocalPosition;
			}
			if (((Component)this).transform.localRotation != _rootLocalRotation)
			{
				((Component)this).transform.localRotation = _rootLocalRotation;
			}
			UpdateSingleSqueezeState();
			float squeezeWeight = EvaluateSingleSqueezeWeight();
			Vector3 desiredRootScale = GetDesiredRootScale(squeezeWeight);
			if (((Component)this).transform.localScale != desiredRootScale)
			{
				((Component)this).transform.localScale = desiredRootScale;
			}
			for (int i = 0; i < _allTransforms.Length; i++)
			{
				Transform val = _allTransforms[i];
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)((Component)this).transform) && val.localScale != _initialChildScales[i])
				{
					val.localScale = _initialChildScales[i];
				}
			}
		}
	}
	public class MikuRendererGuard : MonoBehaviour
	{
		private const float RefreshInterval = 0.1f;

		private float _nextRefreshTime;

		private Item _boundItem;

		private Renderer[] _cachedRenderers = Array.Empty<Renderer>();

		public void Bind(Item item)
		{
			_boundItem = item;
		}

		private void LateUpdate()
		{
			if (!Plugin.ModEnabled || !Plugin.EnableVisibilityGuard || Time.time < _nextRefreshTime)
			{
				return;
			}
			_nextRefreshTime = Time.time + 0.1f;
			if (!((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(true);
			}
			int num = (((Object)(object)_boundItem != (Object)null) ? ((Component)_boundItem).gameObject.layer : ((Component)this).gameObject.layer);
			if (((Component)this).gameObject.layer != num)
			{
				((Component)this).gameObject.layer = num;
			}
			Renderer[] renderableChildren = GetRenderableChildren();
			foreach (Renderer val in renderableChildren)
			{
				if (!((Object)(object)val == (Object)null) && !ItemPatch.IsSuppressedReplacementRenderer(val))
				{
					EnsureRendererVisible(val, num);
				}
			}
			if ((Object)(object)_boundItem != (Object)null && Time.frameCount % 300 == 0)
			{
				ItemPatch.ForceNormalizeAllMaterials(((Component)this).transform);
			}
		}

		private Renderer[] GetRenderableChildren()
		{
			if (_cachedRenderers.Length == 0 || HasNullRenderer(_cachedRenderers))
			{
				_cachedRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
			}
			return _cachedRenderers;
		}

		private static bool HasNullRenderer(Renderer[] renderers)
		{
			for (int i = 0; i < renderers.Length; i++)
			{
				if ((Object)(object)renderers[i] == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static void EnsureRendererVisible(Renderer renderer, int targetLayer)
		{
			if (!((Component)renderer).gameObject.activeSelf)
			{
				((Component)renderer).gameObject.SetActive(true);
			}
			if (renderer.forceRenderingOff)
			{
				renderer.forceRenderingOff = false;
			}
			if (!renderer.enabled)
			{
				renderer.enabled = true;
			}
			renderer.SetPropertyBlock((MaterialPropertyBlock)null);
			((Component)renderer).gameObject.layer = targetLayer;
			renderer.allowOcclusionWhenDynamic = false;
		}
	}
	[HarmonyPatch(typeof(Item))]
	public class ItemPatch
	{
		private const int VisibleLayer = 0;

		private static readonly Color MikuMaterialTint = new Color(0.98f, 1f, 1f, 1f);

		private const string MikuVisualName = "FufuVisual";

		private static readonly Vector3 WorldMikuLocalPositionOffset = new Vector3(0f, 0.08f, 0.03f);

		private static readonly Quaternion WorldMikuLocalRotationOffset = Quaternion.Euler(0f, 180f, 0f);

		private static readonly Vector3 HeldMikuLocalPositionOffset = new Vector3(0f, 0f, 0f);

		private static readonly Quaternion HeldMikuLocalRotationOffset = Quaternion.Euler(10f, 180f, 0f);

		private static readonly string[] AltTextureRendererKeywords = new string[1] { "装饰" };

		private static readonly string[] MainTextureRendererKeywords = new string[4] { "头发", "衣服", "身子", "马尾" };

		private static readonly string[] ClothingRendererKeywords = new string[1] { "衣服" };

		private static readonly string[] UnwantedFootKeywords = new string[3] { "hand", "glove", "mitten" };

		private const float BaseModelScaleFactor = 0.25f;

		private static Shader _cachedPreferredShader;

		private static bool IsBingBong(Item item)
		{
			if ((Object)(object)item != (Object)null)
			{
				return ((Object)item).name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static bool IsReplacementItemName(string itemName)
		{
			if (string.IsNullOrEmpty(itemName))
			{
				return false;
			}
			if (itemName.IndexOf("Bing Bong", StringComparison.OrdinalIgnoreCase) < 0 && itemName.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return itemName.IndexOf("Fufu", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		internal static bool IsMikuTransform(Transform transform)
		{
			if ((Object)(object)transform != (Object)null)
			{
				return (Object)(object)((Component)transform).GetComponentInParent<MikuMarker>() != (Object)null;
			}
			return false;
		}

		internal static bool IsSuppressedReplacementRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer != (Object)null)
			{
				return (Object)(object)((Component)renderer).GetComponent<MikuSuppressedRendererSource>() != (Object)null;
			}
			return false;
		}

		private static bool IsInBackpack(Item item)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				return (int)item.itemState == 2;
			}
			return false;
		}

		private static bool IsHeld(Item item)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((Object)(object)item != (Object)null)
			{
				return (int)item.itemState == 1;
			}
			return false;
		}

		private static bool ShouldShowReplacement(Item item)
		{
			if ((Object)(object)item != (Object)null)
			{
				return Plugin.ModEnabled;
			}
			return false;
		}

		private static void GetAuthoredRootPose(Transform mikuRoot, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
		{
			//IL_001e: 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_002f: 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_003b: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_004c: 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_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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			MikuPoseTemplate mikuPoseTemplate = (((Object)(object)mikuRoot != (Object)null) ? ((Component)mikuRoot).GetComponent<MikuPoseTemplate>() : null);
			if ((Object)(object)mikuPoseTemplate != (Object)null)
			{
				localPosition = mikuPoseTemplate.AuthoredLocalPosition;
				localRotation = mikuPoseTemplate.AuthoredLocalRotation;
				localScale = mikuPoseTemplate.AuthoredLocalScale;
			}
			else if ((Object)(object)mikuRoot != (Object)null)
			{
				localPosition = mikuRoot.localPosition;
				localRotation = mikuRoot.localRotation;
				localScale = ((mikuRoot.localScale == Vector3.zero) ? Vector3.one : mikuRoot.localScale);
			}
			else
			{
				localPosition = Vector3.zero;
				localRotation = Quaternion.identity;
				localScale = Vector3.one;
			}
		}

		private static Vector3 ResolveScaleByState(Item item, Vector3 authoredScale)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_0022: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			float num = (IsInBackpack(item) ? Plugin.BackpackScaleMultiplier : Plugin.WorldScaleMultiplier);
			return ApplyPlayerFacingScale((authoredScale == Vector3.zero) ? Vector3.one : authoredScale) * 0.25f * num;
		}

		private static Vector3 ApplyPlayerFacingScale(Vector3 scale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(Mathf.Abs(scale.x), Mathf.Abs(scale.y), Mathf.Abs(scale.z));
		}

		private static void ResolvePoseByState(Item item, Transform mikuRoot, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//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)
			GetAuthoredRootPose(mikuRoot, out var localPosition2, out var localRotation2, out var localScale2);
			ResolvePoseByState(item, localPosition2, localRotation2, localScale2, out localPosition, out localRotation, out localScale);
		}

		private static void ResolvePoseByState(Item item, Vector3 authoredPosition, Quaternion authoredRotation, Vector3 authoredScale, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0065: Unknown result type (might be due to invalid IL or missing references)
			localScale = ResolveScaleByState(item, authoredScale);
			if (IsHeld(item))
			{
				localPosition = authoredPosition + HeldMikuLocalPositionOffset;
				localRotation = authoredRotation * HeldMikuLocalRotationOffset;
			}
			else
			{
				localPosition = authoredPosition + WorldMikuLocalPositionOffset;
				localRotation = (IsInBackpack(item) ? authoredRotation : (authoredRotation * WorldMikuLocalRotationOffset));
			}
		}

		private static Transform FindMikuRoot(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			MikuMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren<MikuMarker>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					return ((Component)componentsInChildren[i]).transform;
				}
			}
			return ((Component)item).transform.Find("FufuVisual");
		}

		private static Texture GetMikuTexture()
		{
			if ((Object)(object)Plugin.MikuMainTexture != (Object)null)
			{
				return (Texture)(object)Plugin.MikuMainTexture;
			}
			return null;
		}

		private static Texture GetAltMikuTexture()
		{
			return (Texture)(object)Plugin.MikuAltTexture;
		}

		private static bool IsMainTextureRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			string obj = ((Object)((Component)renderer).gameObject).name?.ToLowerInvariant() ?? string.Empty;
			string text = ((Object)renderer).name?.ToLowerInvariant() ?? string.Empty;
			string text2 = obj + " " + text;
			if (ContainsKeyword(obj, MainTextureRendererKeywords) || ContainsKeyword(text, MainTextureRendererKeywords))
			{
				return true;
			}
			if (text2.Contains("cloth") || text2.Contains("clothes") || text2.Contains("dress") || text2.Contains("shirt"))
			{
				return true;
			}
			if (text2.Contains("头发") || text2.Contains("发"))
			{
				return true;
			}
			if (text2.Contains("身体") || text2.Contains("身子"))
			{
				return true;
			}
			if (text2.Contains("马尾") || text2.Contains("尾巴"))
			{
				return true;
			}
			if (text2.Contains("衣服") || text2.Contains("服装"))
			{
				return true;
			}
			return false;
		}

		private static bool IsClothingRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			string obj = ((Object)((Component)renderer).gameObject).name?.ToLowerInvariant() ?? string.Empty;
			string text = ((Object)renderer).name?.ToLowerInvariant() ?? string.Empty;
			string text2 = obj + " " + text;
			if (ContainsKeyword(obj, ClothingRendererKeywords) || ContainsKeyword(text, ClothingRendererKeywords))
			{
				return true;
			}
			if (text2.Contains("cloth") || text2.Contains("clothes") || text2.Contains("dress") || text2.Contains("shirt"))
			{
				return true;
			}
			if (text2.Contains("衣服") || text2.Contains("服装"))
			{
				return true;
			}
			return false;
		}

		private static bool IsAltTextureRenderer(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			string value = ((Object)((Component)renderer).gameObject).name?.ToLowerInvariant() ?? string.Empty;
			string value2 = ((Object)renderer).name?.ToLowerInvariant() ?? string.Empty;
			if (!ContainsKeyword(value, AltTextureRendererKeywords))
			{
				return ContainsKeyword(value2, AltTextureRendererKeywords);
			}
			return true;
		}

		private static Texture TryGetTexture(Material material)
		{
			if ((Object)(object)material == (Object)null)
			{
				return null;
			}
			if (material.HasProperty("_BaseMap"))
			{
				Texture texture = material.GetTexture("_BaseMap");
				if ((Object)(object)texture != (Object)null)
				{
					return texture;
				}
			}
			if (material.HasProperty("_MainTex"))
			{
				return material.GetTexture("_MainTex");
			}
			return null;
		}

		private static bool TrySetTextureSafe(Material material, string propertyName, Texture texture)
		{
			if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName))
			{
				return false;
			}
			try
			{
				material.SetTexture(propertyName, texture);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.VerboseLog("[ItemPatch] Skip SetTexture on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message);
				return false;
			}
		}

		private static void TrySetTextureTransformSafe(Material material, string propertyName, Vector2 scale, Vector2 offset)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName))
			{
				return;
			}
			try
			{
				material.SetTextureScale(propertyName, scale);
				material.SetTextureOffset(propertyName, offset);
			}
			catch (Exception ex)
			{
				Plugin.VerboseLog("[ItemPatch] Skip texture transform on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message);
			}
		}

		private static void ApplyMikuTextureSafe(Material material, Texture mikuTexture)
		{
			//IL_0034: 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_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)
			if (!((Object)(object)material == (Object)null) && !((Object)(object)mikuTexture == (Object)null))
			{
				try
				{
					material.mainTexture = mikuTexture;
				}
				catch
				{
				}
				if (TrySetTextureSafe(material, "_BaseMap", mikuTexture))
				{
					TrySetTextureTransformSafe(material, "_BaseMap", Vector2.one, Vector2.zero);
				}
				if (TrySetTextureSafe(material, "_MainTex", mikuTexture))
				{
					TrySetTextureTransformSafe(material, "_MainTex", Vector2.one, Vector2.zero);
				}
			}
		}

		private static void DisableOptionalSurfaceTextures(Material material)
		{
			if (!((Object)(object)material == (Object)null))
			{
				TrySetTextureSafe(material, "_BumpMap", null);
				TrySetTextureSafe(material, "_NormalMap", null);
				TrySetTextureSafe(material, "_OcclusionMap", null);
				TrySetTextureSafe(material, "_MetallicGlossMap", null);
				TrySetTextureSafe(material, "_SpecGlossMap", null);
				material.DisableKeyword("_NORMALMAP");
				material.DisableKeyword("_METALLICSPECGLOSSMAP");
				material.DisableKeyword("_OCCLUSIONMAP");
			}
		}

		private static void OptimizeTextureSampling(Texture texture)
		{
			Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null);
			if (!((Object)(object)val == (Object)null))
			{
				((Texture)val).filterMode = (FilterMode)2;
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Texture)val).anisoLevel = Mathf.Max(((Texture)val).anisoLevel, 16);
				((Texture)val).mipMapBias = Mathf.Min(((Texture)val).mipMapBias, -0.75f);
			}
		}

		private static void ApplyRealisticMaterialTuning(Material material)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Tint"))
				{
					material.SetColor("_Tint", MikuMaterialTint);
				}
				if (material.HasProperty("_BaseColor"))
				{
					material.SetColor("_BaseColor", MikuMaterialTint);
				}
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", MikuMaterialTint);
				}
				if (material.HasProperty("_Smoothness"))
				{
					material.SetFloat("_Smoothness", 0.1f);
				}
				if (material.HasProperty("_Glossiness"))
				{
					material.SetFloat("_Glossiness", 0.1f);
				}
				if (material.HasProperty("_Metallic"))
				{
					material.SetFloat("_Metallic", 0f);
				}
				if (material.HasProperty("_BumpScale"))
				{
					material.SetFloat("_BumpScale", 0f);
				}
				if (material.HasProperty("_OcclusionStrength"))
				{
					material.SetFloat("_OcclusionStrength", 0f);
				}
				if (material.HasProperty("_SpecularHighlights"))
				{
					material.SetFloat("_SpecularHighlights", 0f);
				}
				if (material.HasProperty("_EnvironmentReflections"))
				{
					material.SetFloat("_EnvironmentReflections", 0f);
				}
				DisableOptionalSurfaceTextures(material);
				if (material.HasProperty("_EmissionColor"))
				{
					material.SetColor("_EmissionColor", Color.black);
					material.DisableKeyword("_EMISSION");
				}
			}
		}

		private static Shader GetPreferredRendererShader()
		{
			if ((Object)(object)_cachedPreferredShader != (Object)null && _cachedPreferredShader.isSupported)
			{
				return _cachedPreferredShader;
			}
			_cachedPreferredShader = null;
			Shader val = Shader.Find("Universal Render Pipeline/Lit");
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				_cachedPreferredShader = val;
				return val;
			}
			val = Shader.Find("Universal Render Pipeline/Unlit");
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				_cachedPreferredShader = val;
				return val;
			}
			val = Shader.Find("W/Peak_Standard");
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				_cachedPreferredShader = val;
				return val;
			}
			val = Shader.Find("Standard");
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				_cachedPreferredShader = val;
				return val;
			}
			val = Shader.Find("Unlit/Texture");
			if ((Object)(object)val != (Object)null && val.isSupported)
			{
				_cachedPreferredShader = val;
				return val;
			}
			return null;
		}

		private static Material CreateFallbackMaterial()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_002e: Expected O, but got Unknown
			Shader preferredRendererShader = GetPreferredRendererShader();
			if ((Object)(object)preferredRendererShader == (Object)null)
			{
				return null;
			}
			return new Material(preferredRendererShader)
			{
				name = "Fufu_Fallback",
				color = Color.white
			};
		}

		private static void ApplyOpaqueSurfaceFlags(Material material, CullMode cullMode)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Surface"))
				{
					material.SetFloat("_Surface", 0f);
				}
				if (material.HasProperty("_Blend"))
				{
					material.SetFloat("_Blend", 0f);
				}
				if (material.HasProperty("_ZWrite"))
				{
					material.SetFloat("_ZWrite", 1f);
				}
				if (material.HasProperty("_SrcBlend"))
				{
					material.SetFloat("_SrcBlend", 1f);
				}
				if (material.HasProperty("_DstBlend"))
				{
					material.SetFloat("_DstBlend", 0f);
				}
				if (material.HasProperty("_Cull"))
				{
					material.SetFloat("_Cull", (float)cullMode);
				}
				if (material.HasProperty("_AlphaClip"))
				{
					material.SetFloat("_AlphaClip", 0f);
				}
				if (material.HasProperty("_Cutoff"))
				{
					material.SetFloat("_Cutoff", 0f);
				}
				if (material.HasProperty("_LOD"))
				{
					material.SetFloat("_LOD", 600f);
				}
				material.renderQueue = 2000;
				material.SetOverrideTag("RenderType", "Opaque");
				material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
				material.EnableKeyword("_SURFACE_TYPE_OPAQUE");
				material.DisableKeyword("_ALPHATEST_ON");
				material.DisableKeyword("_ALPHABLEND_ON");
				material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
				material.DisableKeyword("LOD_FADE_CROSSFADE");
			}
		}

		private static int GetRendererSubMeshCount(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return 1;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
			{
				return Mathf.Max(1, val.sharedMesh.subMeshCount);
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null)
			{
				return Mathf.Max(1, component.sharedMesh.subMeshCount);
			}
			return 1;
		}

		private static Material PickFallbackMaterial(Material[] materials)
		{
			if (materials != null)
			{
				for (int i = 0; i < materials.Length; i++)
				{
					if ((Object)(object)materials[i] != (Object)null)
					{
						return materials[i];
					}
				}
			}
			return Plugin.MochiMaterial ?? Plugin.RuntimeMikuMaterial;
		}

		private static Material[] CreateNormalizedMaterialArray(Material[] sourceMaterials, int subMeshCount)
		{
			int num = Mathf.Max(1, subMeshCount);
			Material[] array = (Material[])(object)new Material[num];
			Material val = PickFallbackMaterial(sourceMaterials);
			for (int i = 0; i < num; i++)
			{
				Material val2 = ((sourceMaterials != null && i < sourceMaterials.Length) ? sourceMaterials[i] : null);
				array[i] = val2 ?? val;
			}
			return array;
		}

		private static bool MaterialArraysMatch(Material[] current, Material[] expected)
		{
			if (current == expected)
			{
				return true;
			}
			if (current == null || expected == null || current.Length != expected.Length)
			{
				return false;
			}
			for (int i = 0; i < current.Length; i++)
			{
				if ((Object)(object)current[i] != (Object)(object)expected[i])
				{
					return false;
				}
			}
			return true;
		}

		private static bool NormalizeRendererMaterialLayout(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null || IsSuppressedReplacementRenderer(renderer))
			{
				return false;
			}
			int rendererSubMeshCount = GetRendererSubMeshCount(renderer);
			Material[] sharedMaterials = renderer.sharedMaterials;
			Material[] array = CreateNormalizedMaterialArray(sharedMaterials, rendererSubMeshCount);
			if (MaterialArraysMatch(sharedMaterials, array))
			{
				return false;
			}
			renderer.sharedMaterials = array;
			return true;
		}

		private static void CopyRendererSettings(Renderer source, MeshRenderer target)
		{
			//IL_0015: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null))
			{
				((Renderer)target).shadowCastingMode = source.shadowCastingMode;
				((Renderer)target).receiveShadows = source.receiveShadows;
				((Renderer)target).lightProbeUsage = source.lightProbeUsage;
				((Renderer)target).reflectionProbeUsage = source.reflectionProbeUsage;
				((Renderer)target).probeAnchor = source.probeAnchor;
				((Renderer)target).allowOcclusionWhenDynamic = source.allowOcclusionWhenDynamic;
				((Renderer)target).enabled = source.enabled;
			}
		}

		private static bool BakeSkinnedRendererToStaticRenderer(SkinnedMeshRenderer source)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0093: 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_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null || (Object)(object)source.sharedMesh == (Object)null || IsSuppressedReplacementRenderer((Renderer)(object)source))
			{
				return false;
			}
			Mesh val = new Mesh
			{
				name = ((Object)source.sharedMesh).name + "_RuntimeBaked"
			};
			try
			{
				source.BakeMesh(val);
			}
			catch (Exception ex)
			{
				Object.Destroy((Object)(object)val);
				Plugin.Log.LogWarning((object)("[ItemPatch] Failed to bake skinned renderer '" + ((Object)source).name + "': " + ex.Message));
				return false;
			}
			GameObject val2 = new GameObject(((Object)((Component)source).gameObject).name + "_Baked");
			val2.transform.SetParent(((Component)source).transform.parent, false);
			val2.transform.localPosition = ((Component)source).transform.localPosition;
			val2.transform.localRotation = ((Component)source).transform.localRotation;
			val2.transform.localScale = ((Component)source).transform.localScale;
			val2.AddComponent<MeshFilter>().sharedMesh = val;
			MeshRenderer val3 = val2.AddComponent<MeshRenderer>();
			CopyRendererSettings((Renderer)(object)source, val3);
			((Renderer)val3).sharedMaterials = CreateNormalizedMaterialArray(((Renderer)source).sharedMaterials, val.subMeshCount);
			if ((Object)(object)((Component)source).gameObject.GetComponent<MikuSuppressedRendererSource>() == (Object)null)
			{
				((Component)source).gameObject.AddComponent<MikuSuppressedRendererSource>();
			}
			((Renderer)source).enabled = false;
			((Renderer)source).forceRenderingOff = true;
			return true;
		}

		private static void RegeneratePrefabRenderers(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			int num = 0;
			SkinnedMeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (BakeSkinnedRendererToStaticRenderer(componentsInChildren[i]))
				{
					num++;
				}
			}
			int num2 = 0;
			MeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren<MeshRenderer>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if (NormalizeRendererMaterialLayout((Renderer)(object)componentsInChildren2[j]))
				{
					num2++;
				}
			}
			ForceNormalizeAllMaterials(mikuRoot);
			if (num > 0 || num2 > 0)
			{
				Plugin.Log.LogInfo((object)("[ItemPatch] Regenerated renderers for prefab '" + ((Object)mikuRoot).name + "': bakedSkinned=" + num + ", normalizedMaterials=" + num2));
			}
		}

		internal static void ForceNormalizeAllMaterials(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			int num = 0;
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || IsSuppressedReplacementRenderer(val))
				{
					continue;
				}
				int rendererSubMeshCount = GetRendererSubMeshCount(val);
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials != null && sharedMaterials.Length > rendererSubMeshCount)
				{
					Material[] array = (Material[])(object)new Material[rendererSubMeshCount];
					for (int j = 0; j < rendererSubMeshCount; j++)
					{
						array[j] = sharedMaterials[j];
					}
					val.sharedMaterials = array;
					num++;
				}
				else if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					Material val2 = Plugin.MochiMaterial ?? Plugin.RuntimeMikuMaterial;
					if ((Object)(object)val2 != (Object)null)
					{
						val.material = val2;
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.Log.LogInfo((object)("[Fix] Normalized materials on " + num + " renderers under '" + ((Object)mikuRoot).name + "'"));
			}
		}

		private static void ReplaceRendererMaterialsCompletely(Renderer renderer, int targetLayer)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null)
			{
				return;
			}
			int rendererSubMeshCount = GetRendererSubMeshCount(renderer);
			if (rendererSubMeshCount == 0)
			{
				return;
			}
			Shader preferredRendererShader = GetPreferredRendererShader();
			if ((Object)(object)preferredRendererShader == (Object)null)
			{
				return;
			}
			bool num = IsAltTextureRenderer(renderer);
			bool flag = IsMainTextureRenderer(renderer);
			bool flag2 = IsClothingRenderer(renderer);
			Texture val = (num ? GetAltMikuTexture() : (flag ? GetMikuTexture() : GetMikuTexture()));
			if ((Object)(object)val == (Object)null && !flag2)
			{
				return;
			}
			Material[] array = (Material[])(object)new Material[rendererSubMeshCount];
			for (int i = 0; i < rendererSubMeshCount; i++)
			{
				Material val2 = new Material(preferredRendererShader);
				((Object)val2).name = "Fufu_" + ((Object)renderer).name + "_" + i;
				val2.color = Color.white;
				val2.renderQueue = 2000;
				ApplyOpaqueSurfaceFlags(val2, (CullMode)0);
				if ((Object)(object)val != (Object)null)
				{
					ApplyMikuTextureSafe(val2, val);
				}
				if (val2.HasProperty("_Smoothness"))
				{
					val2.SetFloat("_Smoothness", 0.1f);
				}
				if (val2.HasProperty("_Glossiness"))
				{
					val2.SetFloat("_Glossiness", 0.1f);
				}
				if (val2.HasProperty("_Metallic"))
				{
					val2.SetFloat("_Metallic", 0f);
				}
				if (val2.HasProperty("_BumpScale"))
				{
					val2.SetFloat("_BumpScale", 0f);
				}
				if (val2.HasProperty("_OcclusionStrength"))
				{
					val2.SetFloat("_OcclusionStrength", 0f);
				}
				if (val2.HasProperty("_SpecularHighlights"))
				{
					val2.SetFloat("_SpecularHighlights", 0f);
				}
				if (val2.HasProperty("_EnvironmentReflections"))
				{
					val2.SetFloat("_EnvironmentReflections", 0f);
				}
				if (val2.HasProperty("_EmissionColor"))
				{
					val2.SetColor("_EmissionColor", Color.black);
					val2.DisableKeyword("_EMISSION");
				}
				array[i] = val2;
			}
			renderer.sharedMaterials = array;
		}

		private static bool HasVisibleReplacementRenderers(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return false;
			}
			Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || IsSuppressedReplacementRenderer(val))
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				if (sharedMaterials == null || sharedMaterials.Length == 0)
				{
					continue;
				}
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if ((Object)(object)sharedMaterials[j] != (Object)null)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void DisableOriginalRenderers(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			Transform val = FindMikuRoot(item);
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			int num = 0;
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsMikuTransform(((Component)val2).transform) && (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)))
				{
					bool enabled = val2.enabled;
					val2.enabled = false;
					val2.forceRenderingOff = true;
					if (enabled)
					{
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.VerboseLog("[Fix] Disabled " + num + " original renderers on item: " + ((Object)item).name);
			}
		}

		private static void EnableOriginalRenderers(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return;
			}
			Transform val = FindMikuRoot(item);
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsMikuTransform(((Component)val2).transform) && (!((Object)(object)val != (Object)null) || !((Component)val2).transform.IsChildOf(val)))
				{
					val2.enabled = true;
				}
			}
		}

		private static void EnableOriginalColliders(Item item)
		{
			Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Collider>(true);
			List<Collider> list = new List<Collider>();
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform))
				{
					val.enabled = true;
					list.Add(val);
				}
			}
			if ((Object)(object)item != (Object)null)
			{
				item.colliders = list.ToArray();
			}
		}

		private static void DisableOriginalColliders(Item item)
		{
			Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform))
				{
					val.enabled = false;
				}
			}
		}

		private static Collider FindColliderTemplate(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !IsMikuTransform(((Component)val).transform))
				{
					return val;
				}
			}
			return null;
		}

		private static Vector3 ClampColliderSize(Vector3 size)
		{
			//IL_0000: 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_0020: 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)
			return new Vector3(Mathf.Max(size.x, 0.02f), Mathf.Max(size.y, 0.02f), Mathf.Max(size.z, 0.02f));
		}

		private static bool HasNegativeScaleInHierarchy(Transform transform)
		{
			//IL_0005: 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)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				Vector3 localScale = val.localScale;
				if (localScale.x < 0f || localScale.y < 0f || localScale.z < 0f)
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static void CopyColliderSettings(Collider source, Collider target)
		{
			if (!((Object)(object)target == (Object)null))
			{
				if ((Object)(object)source != (Object)null)
				{
					target.isTrigger = source.isTrigger;
					target.sharedMaterial = source.sharedMaterial;
					target.contactOffset = source.contactOffset;
				}
				target.enabled = true;
			}
		}

		private static Collider AddBoxColliderForMeshRenderer(MeshRenderer renderer, Collider templateCollider)
		{
			//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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null)
			{
				return null;
			}
			if (HasNegativeScaleInHierarchy(((Component)renderer).transform))
			{
				return null;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null)
			{
				return null;
			}
			Bounds bounds = component.sharedMesh.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			if (((Vector3)(ref size)).sqrMagnitude <= 0f)
			{
				return null;
			}
			BoxCollider val = ((Component)renderer).gameObject.GetComponent<BoxCollider>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)renderer).gameObject.AddComponent<BoxCollider>();
			}
			val.center = ((Bounds)(ref bounds)).center;
			val.size = ClampColliderSize(((Bounds)(ref bounds)).size);
			CopyColliderSettings(templateCollider, (Collider)(object)val);
			return (Collider)(object)val;
		}

		private static Collider AddBoxColliderForSkinnedRenderer(SkinnedMeshRenderer renderer, Collider templateCollider)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0053: 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_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null)
			{
				return null;
			}
			if (HasNegativeScaleInHierarchy(((Component)renderer).transform))
			{
				return null;
			}
			Bounds val = ((Renderer)renderer).localBounds;
			Vector3 size = ((Bounds)(ref val)).size;
			if (((Vector3)(ref size)).sqrMagnitude <= 0f && (Object)(object)renderer.sharedMesh != (Object)null)
			{
				val = renderer.sharedMesh.bounds;
			}
			size = ((Bounds)(ref val)).size;
			if (((Vector3)(ref size)).sqrMagnitude <= 0f)
			{
				return null;
			}
			BoxCollider val2 = ((Component)renderer).gameObject.GetComponent<BoxCollider>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ((Component)renderer).gameObject.AddComponent<BoxCollider>();
			}
			val2.center = ((Bounds)(ref val)).center;
			val2.size = ClampColliderSize(((Bounds)(ref val)).size);
			CopyColliderSettings(templateCollider, (Collider)(object)val2);
			return (Collider)(object)val2;
		}

		private static void EncapsulateBoundsCorners(ref Bounds aggregateBounds, ref bool hasBounds, Transform root, Bounds rendererBounds)
		{
			//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)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0027: 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_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_003f: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_005e: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_008c: 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)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00a9: 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_00b1: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//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_00d6: 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)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: 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)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_0154: 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_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: 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)
			Vector3 center = ((Bounds)(ref rendererBounds)).center;
			Vector3 extents = ((Bounds)(ref rendererBounds)).extents;
			Vector3[] array = (Vector3[])(object)new Vector3[8]
			{
				center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z),
				center + new Vector3(0f - extents.x, 0f - extents.y, extents.z),
				center + new Vector3(0f - extents.x, extents.y, 0f - extents.z),
				center + new Vector3(0f - extents.x, extents.y, extents.z),
				center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z),
				center + new Vector3(extents.x, 0f - extents.y, extents.z),
				center + new Vector3(extents.x, extents.y, 0f - extents.z),
				center + new Vector3(extents.x, extents.y, extents.z)
			};
			for (int i = 0; i < array.Length; i++)
			{
				Vector3 val = root.InverseTransformPoint(array[i]);
				if (!hasBounds)
				{
					aggregateBounds = new Bounds(val, Vector3.zero);
					hasBounds = true;
				}
				else
				{
					((Bounds)(ref aggregateBounds)).Encapsulate(val);
				}
			}
		}

		private static Collider AddFallbackRootCollider(Transform mikuRoot, Collider templateCollider)
		{
			//IL_0015: 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_0079: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return null;
			}
			Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			Bounds aggregateBounds = default(Bounds);
			bool hasBounds = false;
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					EncapsulateBoundsCorners(ref aggregateBounds, ref hasBounds, mikuRoot, val.bounds);
				}
			}
			if (!hasBounds)
			{
				return null;
			}
			BoxCollider val2 = ((Component)mikuRoot).gameObject.GetComponent<BoxCollider>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = ((Component)mikuRoot).gameObject.AddComponent<BoxCollider>();
			}
			val2.center = ((Bounds)(ref aggregateBounds)).center;
			val2.size = ClampColliderSize(((Bounds)(ref aggregateBounds)).size);
			CopyColliderSettings(templateCollider, (Collider)(object)val2);
			return (Collider)(object)val2;
		}

		private static void RebuildModelColliders(Item item, Transform mikuRoot)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			Collider templateCollider = FindColliderTemplate(item);
			Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
			List<Collider> list = new List<Collider>();
			MeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsSuppressedReplacementRenderer((Renderer)(object)val2))
				{
					Collider val3 = AddBoxColliderForMeshRenderer(val2, templateCollider);
					if ((Object)(object)val3 != (Object)null)
					{
						list.Add(val3);
					}
				}
			}
			SkinnedMeshRenderer[] componentsInChildren3 = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val4 in componentsInChildren3)
			{
				if (!((Object)(object)val4 == (Object)null) && !IsSuppressedReplacementRenderer((Renderer)(object)val4))
				{
					Collider val5 = AddBoxColliderForSkinnedRenderer(val4, templateCollider);
					if ((Object)(object)val5 != (Object)null)
					{
						list.Add(val5);
					}
				}
			}
			if (list.Count == 0)
			{
				Collider val6 = AddFallbackRootCollider(mikuRoot, templateCollider);
				if ((Object)(object)val6 != (Object)null)
				{
					list.Add(val6);
				}
			}
			if (list.Count > 0)
			{
				item.colliders = list.ToArray();
				DisableOriginalColliders(item);
			}
		}

		private static void EnsureModelColliders(Item item, Transform mikuRoot)
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null))
			{
				Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Collider>(true);
				if (componentsInChildren.Length == 0)
				{
					RebuildModelColliders(item, mikuRoot);
					componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Collider>(true);
				}
				if (componentsInChildren.Length != 0)
				{
					item.colliders = componentsInChildren;
					DisableOriginalColliders(item);
				}
			}
		}

		private static int DetermineTargetLayer(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return 0;
			}
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform))
				{
					return ((Component)val).gameObject.layer;
				}
			}
			return ((Component)item).gameObject.layer;
		}

		private static void ConfigureMikuRenderer(Renderer renderer, int targetLayer)
		{
			((Component)renderer).gameObject.layer = targetLayer;
			renderer.allowOcclusionWhenDynamic = false;
			renderer.shadowCastingMode = (ShadowCastingMode)1;
			renderer.receiveShadows = true;
			renderer.forceRenderingOff = false;
			renderer.enabled = true;
			renderer.SetPropertyBlock((MaterialPropertyBlock)null);
			if (!((Component)renderer).gameObject.activeSelf)
			{
				((Component)renderer).gameObject.SetActive(true);
			}
		}

		private static bool RendererHasMainTexSlot(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			Material[] sharedMaterials = renderer.sharedMaterials;
			if (sharedMaterials == null || sharedMaterials.Length == 0)
			{
				return false;
			}
			foreach (Material val in sharedMaterials)
			{
				if ((Object)(object)val != (Object)null && (val.HasProperty("_MainTex") || val.HasProperty("_BaseMap")))
				{
					return true;
				}
			}
			return false;
		}

		private static Renderer[] BuildAdditionalRenderers(Renderer primaryRenderer, Renderer[] renderers)
		{
			if (renderers == null || renderers.Length == 0)
			{
				return Array.Empty<Renderer>();
			}
			List<Renderer> list = new List<Renderer>();
			foreach (Renderer val in renderers)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)primaryRenderer))
				{
					list.Add(val);
				}
			}
			if (list.Count != 0)
			{
				return list.ToArray();
			}
			return Array.Empty<Renderer>();
		}

		private static bool TryGetOriginalItemRenderers(Item item, out Renderer primaryRenderer, out Renderer[] additionalRenderers)
		{
			primaryRenderer = null;
			additionalRenderers = Array.Empty<Renderer>();
			if ((Object)(object)item == (Object)null)
			{
				return false;
			}
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			List<Renderer> list = new List<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform) && !IsSuppressedReplacementRenderer(val))
				{
					list.Add(val);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			for (int j = 0; j < list.Count; j++)
			{
				Renderer val2 = list[j];
				if ((Object)(object)primaryRenderer == (Object)null)
				{
					primaryRenderer = val2;
				}
				if (RendererHasMainTexSlot(val2))
				{
					primaryRenderer = val2;
					break;
				}
			}
			if ((Object)(object)primaryRenderer == (Object)null)
			{
				return false;
			}
			additionalRenderers = BuildAdditionalRenderers(primaryRenderer, list.ToArray());
			return true;
		}

		private static void EnsureItemRendererRefs(Item item, Transform mikuRoot)
		{
			if (Plugin.KeepOriginalRendererRefs && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers))
			{
				item.mainRenderer = primaryRenderer;
				item.addtlRenderers = additionalRenderers;
				return;
			}
			Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren.Length == 0)
			{
				return;
			}
			Renderer val = null;
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsSuppressedReplacementRenderer(val2))
				{
					if ((Object)(object)val == (Object)null)
					{
						val = val2;
					}
					if (RendererHasMainTexSlot(val2))
					{
						val = val2;
						break;
					}
				}
			}
			if (!((Object)(object)val == (Object)null))
			{
				item.mainRenderer = val;
				item.addtlRenderers = BuildAdditionalRenderers(val, componentsInChildren);
			}
		}

		private static void RestoreOriginalItemRendererRefs(Item item)
		{
			if (!((Object)(object)item == (Object)null) && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers))
			{
				item.mainRenderer = primaryRenderer;
				item.addtlRenderers = additionalRenderers;
			}
		}

		private static void RemoveReplacement(Item item, Transform mikuRoot)
		{
			EnableOriginalRenderers(item);
			EnableOriginalColliders(item);
			RestoreOriginalItemRendererRefs(item);
			if ((Object)(object)mikuRoot != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)mikuRoot).gameObject);
			}
		}

		private static void ApplyInitialMikuRendererSetup(Item item, Transform mikuRoot)
		{
			int num = DetermineTargetLayer(item);
			((Component)mikuRoot).gameObject.layer = num;
			MeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<MeshRenderer>(true);
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			Plugin.VerboseLog("[ItemPatch] Renderer layout for " + ((Object)item).name + ": MeshRenderers=" + componentsInChildren.Length + ", SkinnedMeshRenderers=" + componentsInChildren2.Length);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !IsSuppressedReplacementRenderer((Renderer)(object)val))
				{
					ConfigureMikuRenderer((Renderer)(object)val, num);
					ReplaceRendererMaterialsCompletely((Renderer)(object)val, num);
				}
			}
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !IsSuppressedReplacementRenderer((Renderer)(object)val2))
				{
					val2.updateWhenOffscreen = true;
					ConfigureMikuRenderer((Renderer)(object)val2, num);
					ReplaceRendererMaterialsCompletely((Renderer)(object)val2, num);
				}
			}
			EnsureItemRendererRefs(item, mikuRoot);
		}

		private static bool IsWhitelistedBehaviour(MonoBehaviour behaviour)
		{
			if (!(behaviour is MikuMarker) && !(behaviour is MikuSuppressedRendererSource) && !(behaviour is MikuPoseTemplate) && !(behaviour is MikuRendererGuard))
			{
				return behaviour is MikuDeformGuard;
			}
			return true;
		}

		private static void SanitizeVisualObject(GameObject visualRoot, int targetLayer)
		{
			Collider[] componentsInChildren = visualRoot.GetComponentsInChildren<Collider>(true);
			foreach (Collider val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.enabled = false;
					Object.Destroy((Object)(object)val);
				}
			}
			Rigidbody[] componentsInChildren2 = visualRoot.GetComponentsInChildren<Rigidbody>(true);
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				if ((Object)(object)componentsInChildren2[j] != (Object)null)
				{
					Object.Destroy((Object)(object)componentsInChildren2[j]);
				}
			}
			Joint[] componentsInChildren3 = visualRoot.GetComponentsInChildren<Joint>(true);
			for (int k = 0; k < componentsInChildren3.Length; k++)
			{
				if ((Object)(object)componentsInChildren3[k] != (Object)null)
				{
					Object.Destroy((Object)(object)componentsInChildren3[k]);
				}
			}
			LODGroup[] componentsInChildren4 = visualRoot.GetComponentsInChildren<LODGroup>(true);
			foreach (LODGroup val2 in componentsInChildren4)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					val2.enabled = false;
					Object.Destroy((Object)(object)val2);
				}
			}
			MonoBehaviour[] componentsInChildren5 = visualRoot.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren5)
			{
				if (!((Object)(object)val3 == (Object)null) && !IsWhitelistedBehaviour(val3))
				{
					((Behaviour)val3).enabled = false;
					Object.Destroy((Object)(object)val3);
				}
			}
			Transform[] componentsInChildren6 = visualRoot.GetComponentsInChildren<Transform>(true);
			foreach (Transform val4 in componentsInChildren6)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					((Component)val4).gameObject.tag = "Untagged";
					((Component)val4).gameObject.layer = targetLayer;
				}
			}
		}

		private static bool ContainsKeyword(string value, string[] keywords)
		{
			if (string.IsNullOrEmpty(value))
			{
				return false;
			}
			string text = value.ToLowerInvariant();
			for (int i = 0; i < keywords.Length; i++)
			{
				if (text.Contains(keywords[i]))
				{
					return true;
				}
			}
			return false;
		}

		private static void RemoveUnwantedFootAttachments(Transform mikuRoot)
		{
			//IL_0034: 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_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)
			Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			int num = 0;
			foreach (Renderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && ContainsKeyword(((Object)((Component)val).gameObject).name, UnwantedFootKeywords))
				{
					Bounds bounds = val.bounds;
					if (!(mikuRoot.InverseTransformPoint(((Bounds)(ref bounds)).center).y > 0.2f))
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
						num++;
					}
				}
			}
			if (num > 0)
			{
				Plugin.VerboseLog("[ItemPatch] Removed unwanted foot attachments: " + num);
			}
		}

		private static void SyncVisibilityState(Item item)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_005c: 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_0055: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindMikuRoot(item);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			int num = DetermineTargetLayer(item);
			((Component)val).gameObject.layer = num;
			ResolvePoseByState(item, val, out var localPosition, out var localRotation, out var localScale);
			if (val.localPosition != localPosition)
			{
				val.localPosition = localPosition;
			}
			if (val.localRotation != localRotation)
			{
				val.localRotation = localRotation;
			}
			if (val.localScale != localScale)
			{
				val.localScale = localScale;
			}
			MikuDeformGuard component = ((Component)val).GetComponent<MikuDeformGuard>();
			if ((Object)(object)component != (Object)null)
			{
				component.SetRootTarget(localPosition, localRotation, localScale);
			}
			bool flag = ShouldShowReplacement(item);
			if (((Component)val).gameObject.activeSelf != flag)
			{
				((Component)val).gameObject.SetActive(flag);
			}
			if (!flag)
			{
				EnableOriginalRenderers(item);
				EnableOriginalColliders(item);
				RestoreOriginalItemRendererRefs(item);
				return;
			}
			EnsureModelColliders(item, val);
			if (HasVisibleReplacementRenderers(val))
			{
				DisableOriginalRenderers(item);
			}
			else
			{
				EnableOriginalRenderers(item);
			}
			Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if ((Object)(object)val2 != (Object)null && !IsSuppressedReplacementRenderer(val2))
				{
					ConfigureMikuRenderer(val2, num);
				}
			}
			EnsureItemRendererRefs(item, val);
		}

		private static Transform EnsureMikuModel(Item item, bool createIfMissing)
		{
			//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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: 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_00ad: 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_00af: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown