Decompiled source of BoxMiku v1.0.1

plugins/BoxMiku.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using 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("BoxMiku")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BoxMiku")]
[assembly: AssemblyTitle("BoxMiku")]
[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 BoxMiku
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.github.Thanks.BoxMiku", "BoxMiku", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const string LegacyPluginId = "com.github.Thanks.BoxMiku";

		private const string BundleFileName = "boxmiku";

		private const string RuntimeReplacementFolderName = "箱MIKU";

		private const string InventoryIconFileName = "BoxMikuUI.png";

		private const string PackageIconFileName = "icon.png";

		private const string ExternalIconFileName = "ミク!.png";

		private const string PrefabAssetPath = "assets/boxmiku/boxmiku.prefab";

		private const string MaterialAssetPath = "assets/boxmiku/m_boxmiku.mat";

		private const string IconTextureAssetPath = "assets/boxmiku/boxmiku_icon.png";

		private const string MainTextureAssetPath = "assets/boxmiku/boxmiku.png";

		private const string ConfigSection = "Main";

		private const float WorldMinScaleMultiplier = 0.4f;

		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 Vector3 DefaultReplacementBaseScale = new Vector3(1.5f, 1.5f, 1.5f);

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

		private static readonly string[] PrefabNameHints = new string[3] { "boxmiku", "miku", "箱" };

		private static readonly string[] MaterialNameHints = new string[3] { "m_boxmiku", "boxmiku", "miku" };

		private static readonly string[] IconTextureNameHints = new string[3] { "boxmiku_icon", "icon", "見本" };

		private static readonly string[] MainTextureNameHints = new string[3] { "boxmiku", "miku", "albedo" };

		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 RuntimeReplacementModel _runtimeReplacementModel;

		public const string Name = "BoxMiku";

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

		public const string Version = "1.0.0";

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

		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 RuntimeReplacementModel RuntimeReplacementModel
		{
			get
			{
				return _runtimeReplacementModel;
			}
			private set
			{
				_runtimeReplacementModel = 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.4f, 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 Vector3 ReplacementBaseScale
		{
			get
			{
				//IL_0012: 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)
				if (RuntimeReplacementModel == null)
				{
					return DefaultReplacementBaseScale;
				}
				return RuntimeReplacementModel.RecommendedBaseScale;
			}
		}

		internal static string ReplacementDisplayName
		{
			get
			{
				if (RuntimeReplacementModel == null)
				{
					return "MIKU";
				}
				return RuntimeReplacementModel.DisplayName;
			}
		}

		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.Thanks.BoxMiku.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 Box Miku 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", "Box Miku Size In World", 0.9f, new ConfigDescription("Scale multiplier for Box Miku while held or lying in the world.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 1.1f), Array.Empty<object>()));
			_backpackScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Box Miku Size In Backpack", 0.4f, new ConfigDescription("Scale multiplier for the Box Miku replacement while stored in the backpack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
		}

		private void LoadAssets()
		{
			Texture2D val = LoadExternalIconTexture();
			RuntimeReplacementModel = RuntimePmxLoader.Load(Path.Combine(directory, "箱MIKU"), Log);
			if (RuntimeReplacementModel != null)
			{
				MochiPrefab = null;
				Bundle = null;
				MochiTexture = val ?? RuntimeReplacementModel.IconTexture ?? RuntimeReplacementModel.PrimaryTexture;
				MikuMainTexture = RuntimeReplacementModel.PrimaryTexture;
				MochiMaterial = RuntimeReplacementModel.PrimaryMaterial;
				RuntimeMikuMaterial = RuntimeReplacementModel.PrimaryMaterial ?? CreateRuntimeMikuMaterial(MikuMainTexture);
				Log.LogInfo((object)("Loaded runtime Box Miku replacement from folder: " + Path.Combine(directory, "箱MIKU")));
				return;
			}
			string text = Path.Combine(directory, "boxmiku");
			Bundle = AssetBundle.LoadFromFile(text);
			if ((Object)(object)Bundle == (Object)null)
			{
				Log.LogError((object)("Failed to load runtime Box Miku assets and failed to load AssetBundle: " + text));
				return;
			}
			MochiPrefab = LoadBundleAssetWithFallback<GameObject>("assets/boxmiku/boxmiku.prefab", PrefabNameHints);
			MochiMaterial = LoadBundleAssetWithFallback<Material>("assets/boxmiku/m_boxmiku.mat", MaterialNameHints);
			MochiTexture = val ?? LoadBundleAssetWithFallback<Texture2D>("assets/boxmiku/boxmiku_icon.png", IconTextureNameHints);
			Texture2D val2 = LoadBundleAssetWithFallback<Texture2D>("assets/boxmiku/boxmiku.png", MainTextureNameHints);
			MikuMainTexture = CreateReadableTexture(val2) ?? val2;
			if ((Object)(object)MochiPrefab == (Object)null)
			{
				Log.LogError((object)"Failed to load replacement prefab from asset bundle.");
				return;
			}
			ConfigureMochiMaterial(MikuMainTexture);
			RuntimeMikuMaterial = CreateRuntimeMikuMaterial(MikuMainTexture);
			if ((Object)(object)RuntimeMikuMaterial == (Object)null)
			{
				Log.LogWarning((object)"Runtime fallback material was not created. The bundled material will be used when available.");
			}
			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.");
			}
		}

		private Texture2D LoadExternalIconTexture()
		{
			string directoryName = Path.GetDirectoryName(directory);
			string[] array = new string[7]
			{
				Path.Combine(directory, "箱MIKU", "BoxMikuUI.png"),
				Path.Combine(directory, "BoxMikuUI.png"),
				string.IsNullOrEmpty(directoryName) ? null : Path.Combine(directoryName, "BoxMikuUI.png"),
				Path.Combine(directory, "icon.png"),
				string.IsNullOrEmpty(directoryName) ? null : Path.Combine(directoryName, "icon.png"),
				Path.Combine(directory, "ミク!.png"),
				Path.Combine(directory, "箱MIKU", "ミク!.png")
			};
			for (int i = 0; i < array.Length; i++)
			{
				Texture2D val = LoadTextureFromFile(array[i], "external icon");
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private Texture2D LoadTextureFromFile(string texturePath, string textureLabel)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Expected O, but got Unknown
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(texturePath) || !File.Exists(texturePath))
			{
				return null;
			}
			try
			{
				using FileStream fileStream = File.OpenRead(texturePath);
				Bitmap val = new Bitmap((Stream)fileStream);
				try
				{
					int width = ((Image)val).Width;
					int height = ((Image)val).Height;
					Color32[] array = (Color32[])(object)new Color32[width * height];
					for (int i = 0; i < height; i++)
					{
						for (int j = 0; j < width; j++)
						{
							Color pixel = val.GetPixel(j, height - 1 - i);
							array[i * width + j] = new Color32(pixel.R, pixel.G, pixel.B, pixel.A);
						}
					}
					Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false, false)
					{
						name = Path.GetFileNameWithoutExtension(texturePath)
					};
					val2.SetPixels32(array);
					((Texture)val2).filterMode = (FilterMode)1;
					((Texture)val2).wrapMode = (TextureWrapMode)1;
					((Texture)val2).anisoLevel = 1;
					val2.Apply(false, false);
					return val2;
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to load " + textureLabel + " texture '" + texturePath + "': " + ex.Message));
				return null;
			}
		}

		internal static GameObject CreateReplacementVisualInstance(string name)
		{
			if (RuntimeReplacementModel != null)
			{
				return RuntimeReplacementModel.Instantiate(name);
			}
			if ((Object)(object)MochiPrefab == (Object)null)
			{
				return null;
			}
			return Object.Instantiate<GameObject>(MochiPrefab);
		}

		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(Texture2D mikuMainTexture)
		{
			if ((Object)(object)MochiMaterial == (Object)null)
			{
				return;
			}
			if ((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;
				}
			}
			if ((Object)(object)mikuMainTexture != (Object)null)
			{
				ApplyTextureSet(MochiMaterial, mikuMainTexture);
			}
			ApplyMikuColorStyle(MochiMaterial);
			VerboseLog("Configured bundled material: " + ((Object)MochiMaterial).name);
		}

		private static bool TryAssignTextureIfMissing(Material material, string propertyName, Texture2D texture)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null || (Object)(object)texture == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName))
			{
				return false;
			}
			try
			{
				if ((Object)(object)material.GetTexture(propertyName) != (Object)null)
				{
					return false;
				}
				material.SetTexture(propertyName, (Texture)(object)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 TryAssignTextureIfMissing(Material material, string[] propertyNames, Texture2D texture)
		{
			if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null) && propertyNames != null)
			{
				for (int i = 0; i < propertyNames.Length; i++)
				{
					TryAssignTextureIfMissing(material, propertyNames[i], texture);
				}
			}
		}

		private static void ApplyTextureSet(Material material, Texture2D albedo)
		{
			if (!((Object)(object)material == (Object)null))
			{
				TryAssignTextureIfMissing(material, PreferredTextureProps, 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 Material CreateRuntimeMikuMaterial(Texture2D texture)
		{
			//IL_0042: 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_0052: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard");
			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 = "BoxMiku_RuntimeMaterial",
				renderQueue = 2000,
				color = Color.white
			};
			if ((Object)(object)texture != (Object)null)
			{
				TryAssignTextureIfMissing(val2, "_BaseMap", texture);
				TryAssignTextureIfMissing(val2, "_MainTex", 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
	{
		private Renderer[] _cachedRenderers;

		private bool _renderersCached;

		private bool _materialsConfigured;

		public Renderer[] CachedRenderers
		{
			get
			{
				if (!_renderersCached || _cachedRenderers == null)
				{
					_cachedRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true);
					_renderersCached = true;
				}
				return _cachedRenderers;
			}
		}

		public bool MaterialsConfigured => _materialsConfigured;

		public void MarkMaterialsConfigured()
		{
			_materialsConfigured = true;
		}

		public void InvalidateCache()
		{
			_renderersCached = false;
			_cachedRenderers = null;
		}
	}
	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];
				}
			}
		}
	}
	[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 = "BoxMiku_Visual";

		private static readonly Vector3 WorldMikuLocalPosition = new Vector3(0f, 0.2f, 0.1f);

		private static readonly Quaternion WorldMikuLocalRotation = Quaternion.identity;

		private static readonly Vector3 HeldMikuLocalPosition = new Vector3(0f, 0.18f, 0.04f);

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

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

		private static readonly Dictionary<int, Renderer[]> _cachedOriginalRenderers = new Dictionary<int, Renderer[]>();

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

		internal static bool IsMikuTransform(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return false;
			}
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				if (((Object)val).name == "BoxMiku_Visual")
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static Transform FindMikuRoot(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)item).transform.Find("BoxMiku_Visual");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			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 null;
		}

		private static int DetermineTargetLayer(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return 0;
			}
			int instanceID = ((Object)item).GetInstanceID();
			if (_cachedTargetLayers.TryGetValue(instanceID, out var value))
			{
				return value;
			}
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			int layer = ((Component)item).gameObject.layer;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (!((Object)(object)componentsInChildren[i] == (Object)null) && !IsMikuTransform(((Component)componentsInChildren[i]).transform))
				{
					layer = ((Component)componentsInChildren[i]).gameObject.layer;
					break;
				}
			}
			_cachedTargetLayers[instanceID] = layer;
			return layer;
		}

		private static Vector3 ResolveScaleByState(Item item)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0016: 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)
			float num = (((int)item.itemState == 2) ? Plugin.BackpackScaleMultiplier : Plugin.WorldScaleMultiplier);
			return Plugin.ReplacementBaseScale * num;
		}

		private static Vector3 ApplyPlayerFacingScale(Vector3 scale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(0f - Mathf.Abs(scale.x), Mathf.Abs(scale.y), 0f - Mathf.Abs(scale.z));
		}

		private static void ResolvePoseByState(Item item, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//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_003f: 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_004a: 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_0011: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 scale = ResolveScaleByState(item);
			if ((int)item.itemState == 1)
			{
				localPosition = HeldMikuLocalPosition;
				localRotation = HeldMikuLocalRotation;
				localScale = ApplyPlayerFacingScale(scale);
			}
			else
			{
				localPosition = WorldMikuLocalPosition;
				localRotation = WorldMikuLocalRotation;
				localScale = ApplyPlayerFacingScale(scale);
			}
		}

		private static Texture GetMikuTexture()
		{
			return (Texture)(((object)Plugin.MikuMainTexture) ?? ((object)(TryGetTexture(Plugin.MochiMaterial) ?? TryGetTexture(Plugin.RuntimeMikuMaterial))));
		}

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

		private static void ApplyMikuTextureSafe(Material material, Texture mikuTexture)
		{
			//IL_0032: 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)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null) && !((Object)(object)mikuTexture == (Object)null))
			{
				if (material.HasProperty("_BaseMap"))
				{
					material.SetTexture("_BaseMap", mikuTexture);
					material.SetTextureScale("_BaseMap", Vector2.one);
					material.SetTextureOffset("_BaseMap", Vector2.zero);
				}
				if (material.HasProperty("_MainTex"))
				{
					material.SetTexture("_MainTex", mikuTexture);
					material.SetTextureScale("_MainTex", Vector2.one);
					material.SetTextureOffset("_MainTex", Vector2.zero);
				}
			}
		}

		private static Material CreateRendererMaterialInstance(Material template = null)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			//IL_004d: Expected O, but got Unknown
			//IL_00c0: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			template = template ?? Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial;
			if ((Object)(object)template == (Object)null)
			{
				Material val = new Material(Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit"))
				{
					color = Color.white
				};
				RuntimePmxLoader.ConfigureOpaqueSurface(val);
				return val;
			}
			Material val2 = new Material(template);
			Texture val3 = TryGetTexture(val2);
			Texture mikuTexture = GetMikuTexture();
			if ((Object)(object)val3 != (Object)null)
			{
				Texture2D val4 = (Texture2D)(object)((val3 is Texture2D) ? val3 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					((Texture)val4).filterMode = (FilterMode)2;
					((Texture)val4).wrapMode = (TextureWrapMode)1;
					((Texture)val4).anisoLevel = Mathf.Max(((Texture)val4).anisoLevel, 16);
				}
			}
			else if ((Object)(object)mikuTexture != (Object)null)
			{
				ApplyMikuTextureSafe(val2, mikuTexture);
			}
			if (val2.HasProperty("_Tint"))
			{
				val2.SetColor("_Tint", MikuMaterialTint);
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", MikuMaterialTint);
			}
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", MikuMaterialTint);
			}
			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);
			}
			return val2;
		}

		private static Material[] BuildMaterialArray(Material[] sourceMaterials, int subMeshCount)
		{
			int num = Mathf.Max(1, subMeshCount);
			Material[] array = (Material[])(object)new Material[num];
			for (int i = 0; i < num; i++)
			{
				Material template = ((sourceMaterials != null && sourceMaterials.Length != 0) ? sourceMaterials[Mathf.Min(i, sourceMaterials.Length - 1)] : null);
				array[i] = CreateRendererMaterialInstance(template);
			}
			return array;
		}

		private static void ApplyMaterialToRenderer(Renderer renderer)
		{
			//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_0041: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)renderer == (Object)null))
			{
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				if ((Object)(object)val != (Object)null && (Object)(object)val.sharedMesh != (Object)null)
				{
					Bounds bounds = val.sharedMesh.bounds;
					((Bounds)(ref bounds)).Expand(0.5f);
					((Renderer)val).localBounds = bounds;
				}
			}
		}

		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 bool RendererNeedsMaterialRepair(Material[] materials, int subMeshCount)
		{
			if (materials == null || materials.Length != Mathf.Max(1, subMeshCount))
			{
				return true;
			}
			for (int i = 0; i < materials.Length; i++)
			{
				if ((Object)(object)materials[i] == (Object)null)
				{
					return true;
				}
			}
			return false;
		}

		private static bool EnsureRendererMaterialIntegrity(Renderer renderer)
		{
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			if (Plugin.RuntimeReplacementModel != null)
			{
				MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
				if ((Object)(object)component != (Object)null && (Object)(object)Plugin.RuntimeReplacementModel.Mesh != (Object)null && (Object)(object)component.sharedMesh != (Object)(object)Plugin.RuntimeReplacementModel.Mesh)
				{
					component.sharedMesh = Plugin.RuntimeReplacementModel.Mesh;
				}
			}
			int rendererSubMeshCount = GetRendererSubMeshCount(renderer);
			Material[] sharedMaterials = renderer.sharedMaterials;
			if (!RendererNeedsMaterialRepair(sharedMaterials, rendererSubMeshCount))
			{
				ApplyMaterialToRenderer(renderer);
				return false;
			}
			if (Plugin.RuntimeReplacementModel != null)
			{
				renderer.sharedMaterials = Plugin.RuntimeReplacementModel.CreateMaterialsForRenderer(rendererSubMeshCount);
			}
			else
			{
				renderer.sharedMaterials = BuildMaterialArray(sharedMaterials, rendererSubMeshCount);
			}
			ApplyMaterialToRenderer(renderer);
			return true;
		}

		private static void EnsureReplacementMaterials(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			MikuMarker component = ((Component)mikuRoot).GetComponent<MikuMarker>();
			Renderer[] array = (((Object)(object)component != (Object)null) ? component.CachedRenderers : ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true));
			bool flag = false;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					EnsureRendererMaterialIntegrity(val);
					flag = true;
				}
			}
			if ((Object)(object)component != (Object)null && flag)
			{
				component.MarkMaterialsConfigured();
			}
		}

		private static Renderer[] GetOriginalRenderers(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return Array.Empty<Renderer>();
			}
			int instanceID = ((Object)item).GetInstanceID();
			if (_cachedOriginalRenderers.TryGetValue(instanceID, out var value))
			{
				bool flag = false;
				for (int i = 0; i < value.Length; i++)
				{
					if ((Object)(object)value[i] == (Object)null)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return value;
				}
			}
			Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Renderer>(true);
			List<Renderer> list = new List<Renderer>();
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				if ((Object)(object)componentsInChildren[j] != (Object)null && !IsMikuTransform(((Component)componentsInChildren[j]).transform))
				{
					list.Add(componentsInChildren[j]);
				}
			}
			Renderer[] array = list.ToArray();
			_cachedOriginalRenderers[instanceID] = array;
			return array;
		}

		private static void DisableOriginalRenderers(Item item)
		{
			Renderer[] originalRenderers = GetOriginalRenderers(item);
			for (int i = 0; i < originalRenderers.Length; i++)
			{
				if ((Object)(object)originalRenderers[i] != (Object)null)
				{
					originalRenderers[i].enabled = false;
				}
			}
		}

		private static void EnableOriginalRenderers(Item item)
		{
			Renderer[] originalRenderers = GetOriginalRenderers(item);
			for (int i = 0; i < originalRenderers.Length; i++)
			{
				if ((Object)(object)originalRenderers[i] != (Object)null)
				{
					originalRenderers[i].enabled = true;
				}
			}
		}

		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 HasVisibleReplacementRenderers(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return false;
			}
			Renderer[] array = ((Component)mikuRoot).GetComponent<MikuMarker>()?.CachedRenderers ?? ((Component)mikuRoot).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] == (Object)null)
				{
					continue;
				}
				Material[] sharedMaterials = array[i].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 SyncVisibilityState(Item item, bool forceRefresh)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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, 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 modEnabled = Plugin.ModEnabled;
			if (((Component)val).gameObject.activeSelf != modEnabled)
			{
				((Component)val).gameObject.SetActive(modEnabled);
			}
			if (!modEnabled)
			{
				EnableOriginalRenderers(item);
				RestoreOriginalItemRendererRefs(item);
			}
			else
			{
				if (!forceRefresh)
				{
					return;
				}
				EnsureReplacementMaterials(val);
				if (HasVisibleReplacementRenderers(val))
				{
					DisableOriginalRenderers(item);
				}
				else
				{
					EnableOriginalRenderers(item);
				}
				Renderer[] array = ((Component)val).GetComponent<MikuMarker>()?.CachedRenderers ?? ((Component)val).GetComponentsInChildren<Renderer>(true);
				for (int i = 0; i < array.Length; i++)
				{
					if ((Object)(object)array[i] != (Object)null)
					{
						ConfigureMikuRenderer(array[i], num);
					}
				}
				EnsureItemRendererRefs(item, val);
			}
		}

		private static void EnsureReplacementAndVisibility(Item item, bool createIfMissing, bool forceRefresh)
		{
			if (!IsBingBong(item))
			{
				return;
			}
			Transform val = FindMikuRoot(item);
			if (!Plugin.ModEnabled)
			{
				if ((Object)(object)val != (Object)null)
				{
					RemoveReplacement(item, val);
				}
				return;
			}
			if ((Object)(object)val == (Object)null)
			{
				val = EnsureMikuModel(item, createIfMissing);
			}
			if (!((Object)(object)val == (Object)null))
			{
				MikuDeformGuard component = ((Component)val).GetComponent<MikuDeformGuard>();
				if ((Object)(object)component != (Object)null)
				{
					component.Bind(item);
				}
				SyncVisibilityState(item, forceRefresh);
			}
		}

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

		private static void SanitizeVisualObject(GameObject visualRoot, int targetLayer)
		{
			Collider[] componentsInChildren = visualRoot.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					componentsInChildren[i].enabled = false;
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
			}
			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 val in componentsInChildren4)
			{
				if ((Object)(object)val != (Object)null)
				{
					val.enabled = false;
					Object.Destroy((Object)(object)val);
				}
			}
			MonoBehaviour[] componentsInChildren5 = visualRoot.GetComponentsInChildren<MonoBehaviour>(true);
			for (int m = 0; m < componentsInChildren5.Length; m++)
			{
				if ((Object)(object)componentsInChildren5[m] != (Object)null && !(componentsInChildren5[m] is MikuMarker))
				{
					((Behaviour)componentsInChildren5[m]).enabled = false;
				}
			}
			Transform[] componentsInChildren6 = visualRoot.GetComponentsInChildren<Transform>(true);
			for (int n = 0; n < componentsInChildren6.Length; n++)
			{
				if ((Object)(object)componentsInChildren6[n] != (Object)null)
				{
					((Component)componentsInChildren6[n]).gameObject.tag = "Untagged";
					((Component)componentsInChildren6[n]).gameObject.layer = targetLayer;
				}
			}
		}

		private static Collider FindColliderTemplate(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && !IsMikuTransform(((Component)componentsInChildren[i]).transform))
				{
					return componentsInChildren[i];
				}
			}
			return null;
		}

		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 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 RebuildModelColliders(Item item, Transform mikuRoot)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: 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_00fd: 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_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			Collider source = FindColliderTemplate(item);
			Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
			}
			List<Collider> list = new List<Collider>();
			MeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren<MeshRenderer>(true);
			Vector3 size;
			foreach (MeshRenderer val in componentsInChildren2)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
				if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null) && !HasNegativeScaleInHierarchy(((Component)val).transform))
				{
					Bounds bounds = component.sharedMesh.bounds;
					size = ((Bounds)(ref bounds)).size;
					if (!(((Vector3)(ref size)).sqrMagnitude <= 0f))
					{
						BoxCollider val2 = ((Component)val).gameObject.GetComponent<BoxCollider>() ?? ((Component)val).gameObject.AddComponent<BoxCollider>();
						val2.center = ((Bounds)(ref bounds)).center;
						val2.size = ClampColliderSize(((Bounds)(ref bounds)).size);
						CopyColliderSettings(source, (Collider)(object)val2);
						list.Add((Collider)(object)val2);
					}
				}
			}
			SkinnedMeshRenderer[] componentsInChildren3 = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null) && !HasNegativeScaleInHierarchy(((Component)val3).transform))
				{
					Bounds val4 = ((Renderer)val3).localBounds;
					size = ((Bounds)(ref val4)).size;
					if (((Vector3)(ref size)).sqrMagnitude <= 0f && (Object)(object)val3.sharedMesh != (Object)null)
					{
						val4 = val3.sharedMesh.bounds;
					}
					size = ((Bounds)(ref val4)).size;
					if (!(((Vector3)(ref size)).sqrMagnitude <= 0f))
					{
						BoxCollider val5 = ((Component)val3).gameObject.GetComponent<BoxCollider>() ?? ((Component)val3).gameObject.AddComponent<BoxCollider>();
						val5.center = ((Bounds)(ref val4)).center;
						val5.size = ClampColliderSize(((Bounds)(ref val4)).size);
						CopyColliderSettings(source, (Collider)(object)val5);
						list.Add((Collider)(object)val5);
					}
				}
			}
			if (list.Count > 0)
			{
				item.colliders = list.ToArray();
			}
		}

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

		private static void DisableOriginalColliders(Item item)
		{
			Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && !IsMikuTransform(((Component)componentsInChildren[i]).transform))
				{
					componentsInChildren[i].enabled = false;
				}
			}
		}

		private static void SyncCollidersByState(Item item, Transform mikuRoot)
		{
			//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)item == (Object)null || (Object)(object)mikuRoot == (Object)null)
			{
				return;
			}
			if ((int)item.itemState == 1)
			{
				SetColliderArrayEnabled(((Component)mikuRoot).GetComponentsInChildren<Collider>(true), enabled: false);
				EnableOriginalColliders(item);
				return;
			}
			Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<Collider>(true);
			if (componentsInChildren.Length == 0)
			{
				RebuildModelColliders(item, mikuRoot);
			}
			if (componentsInChildren.Length != 0)
			{
				SetColliderArrayEnabled(componentsInChildren, enabled: true);
				item.colliders = componentsInChildren;
				DisableOriginalColliders(item);
			}
		}

		private static void SetColliderArrayEnabled(Collider[] colliders, bool enabled)
		{
			if (colliders == null)
			{
				return;
			}
			for (int i = 0; i < colliders.Length; i++)
			{
				if ((Object)(object)colliders[i] != (Object)null)
				{
					colliders[i].enabled = enabled;
				}
			}
		}

		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;
			}
			for (int i = 0; i < sharedMaterials.Length; i++)
			{
				if ((Object)(object)sharedMaterials[i] != (Object)null && sharedMaterials[i].HasProperty("_MainTex"))
				{
					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>();
			for (int i = 0; i < renderers.Length; i++)
			{
				if ((Object)(object)renderers[i] != (Object)null && (Object)(object)renderers[i] != (Object)(object)primaryRenderer)
				{
					list.Add(renderers[i]);
				}
			}
			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[] originalRenderers = GetOriginalRenderers(item);
			if (originalRenderers.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < originalRenderers.Length; i++)
			{
				if ((Object)(object)primaryRenderer == (Object)null)
				{
					primaryRenderer = originalRenderers[i];
				}
				if (RendererHasMainTexSlot(originalRenderers[i]))
				{
					primaryRenderer = originalRenderers[i];
					break;
				}
			}
			if ((Object)(object)primaryRenderer == (Object)null)
			{
				return false;
			}
			additionalRenderers = BuildAdditionalRenderers(primaryRenderer, originalRenderers);
			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;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (!((Object)(object)componentsInChildren[i] == (Object)null))
				{
					if ((Object)(object)val == (Object)null)
					{
						val = componentsInChildren[i];
					}
					if (RendererHasMainTexSlot(componentsInChildren[i]))
					{
						val = componentsInChildren[i];
						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 Transform EnsureMikuModel(Item item, bool createIfMissing)
		{
			//IL_0071: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			Transform val = FindMikuRoot(item);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if (!createIfMissing)
			{
				return null;
			}
			GameObject val2 = Plugin.CreateReplacementVisualInstance("BoxMiku_Visual");
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			val2.transform.SetParent(((Component)item).transform, false);
			((Object)val2).name = "BoxMiku_Visual";
			val2.SetActive(true);
			int targetLayer = (val2.layer = DetermineTargetLayer(item));
			ResolvePoseByState(item, out var localPosition, out var localRotation, out var localScale);
			val2.transform.localPosition = localPosition;
			val2.transform.localRotation = localRotation;
			val2.transform.localScale = localScale;
			MikuMarker mikuMarker = val2.GetComponent<MikuMarker>() ?? val2.AddComponent<MikuMarker>();
			SanitizeVisualObject(val2, targetLayer);
			MikuDeformGuard obj = val2.GetComponent<MikuDeformGuard>() ?? val2.AddComponent<MikuDeformGuard>();
			obj.Bind(item);
			obj.Initialize(localPosition, localRotation, localScale);
			EnsureReplacementMaterials(val2.transform);
			MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(true);
			SkinnedMeshRenderer[] componentsInChildren2 = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				ConfigureMikuRenderer((Renderer)(object)componentsInChildren[i], targetLayer);
			}
			for (int j = 0; j < componentsInChildren2.Length; j++)
			{
				componentsInChildren2[j].updateWhenOffscreen = true;
				ConfigureMikuRenderer((Renderer)(object)componentsInChildren2[j], targetLayer);
			}
			mikuMarker.MarkMaterialsConfigured();
			EnsureItemRendererRefs(item, val2.transform);
			RebuildModelColliders(item, val2.transform);
			return val2.transform;
		}

		[HarmonyPatch("Start")]
		[HarmonyPostfix]
		public static void Item_Start(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: true, forceRefresh: true);
		}

		[HarmonyPatch("OnEnable")]
		[HarmonyPostfix]
		public static void Item_OnEnable(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: true, forceRefresh: true);
		}

		[HarmonyPatch("SetState")]
		[HarmonyPrefix]
		public static void Item_SetState_Prefix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: true, forceRefresh: true);
		}

		[HarmonyPatch("SetState")]
		[HarmonyPostfix]
		public static void Item_SetState_Postfix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: true, forceRefresh: true);
		}

		[HarmonyPatch("Update")]
		[HarmonyPostfix]
		public static void Item_Update_Postfix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: false, forceRefresh: false);
		}

		[HarmonyPatch("RequestPickup")]
		[HarmonyPrefix]
		public static void Item_RequestPickup_Prefix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: true, forceRefresh: true);
		}

		[HarmonyPatch("HideRenderers")]
		[HarmonyPrefix]
		public static bool Item_HideRenderers_Prefix(Item __instance)
		{
			//IL_0031: 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_0072: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.ModEnabled || !IsBingBong(__instance))
			{
				return true;
			}
			Transform val = EnsureMikuModel(__instance, createIfMissing: false);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			ResolvePoseByState(__instance, out var localPosition, out var localRotation, out var localScale);
			val.localPosition = localPosition;
			val.localRotation = localRotation;
			val.localScale = localScale;
			if (!((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(true);
			}
			MikuDeformGuard component = ((Component)val).GetComponent<MikuDeformGuard>();
			if ((Object)(object)component != (Object)null)
			{
				component.SetRootTarget(localPosition, localRotation, localScale);
			}
			SyncCollidersByState(__instance, val);
			EnsureReplacementMaterials(val);
			int targetLayer = DetermineTargetLayer(__instance);
			Renderer[] array = ((Component)val).GetComponent<MikuMarker>()?.CachedRenderers ?? ((Component)val).GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					ConfigureMikuRenderer(array[i], targetLayer);
				}
			}
			DisableOriginalRenderers(__instance);
			EnsureItemRendererRefs(__instance, val);
			return false;
		}

		[HarmonyPatch("PutInBackpackRPC")]
		[HarmonyPostfix]
		public static void Item_PutInBackpackRPC_Postfix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: false, forceRefresh: true);
		}

		[HarmonyPatch("ClearDataFromBackpack")]
		[HarmonyPostfix]
		public static void Item_ClearDataFromBackpack_Postfix(Item __instance)
		{
			EnsureReplacementAndVisibility(__instance, createIfMissing: false, forceRefresh: true);
		}

		[HarmonyPatch(typeof(ItemUIData), "GetIcon")]
		[HarmonyPostfix]
		public static void Item_GetIcon(ItemUIData __instance, ref Texture2D __result)
		{
			if (Plugin.ModEnabled && __instance.itemName == "Bing Bong" && (Object)(object)Plugin.MochiTexture != (Object)null)
			{
				__result = Plugin.MochiTexture;
			}
		}

		[HarmonyPatch("GetName")]
		[HarmonyPostfix]
		public static void Item_GetName_Postfix(Item __instance, ref string __result)
		{
			if (Plugin.ModEnabled && IsBingBong(__instance))
			{
				__result = Plugin.ReplacementDisplayName;
			}
		}

		[HarmonyPatch("GetItemName")]
		[HarmonyPostfix]
		public static void Item_GetItemName_Postfix(Item __instance, ref string __result)
		{
			if (Plugin.ModEnabled && IsBingBong(__instance))
			{
				__result = Plugin.ReplacementDisplayName;
			}
		}
	}
	[HarmonyPatch]
	public static class MikuTintCompatibilityPatch
	{
		private delegate void ItemCookingIntMethod(ItemCooking instance, int value);

		private static readonly FieldRef<BackpackOnBackVisuals, MeshRenderer[]> BackpackRenderersRef = AccessTools.FieldRefAccess<BackpackOnBackVisuals, MeshRenderer[]>("renderers");

		private static readonly FieldRef<BackpackOnBackVisuals, Color[]> BackpackDefaultTintsRef = AccessTools.FieldRefAccess<BackpackOnBackVisuals, Color[]>("defaultTints");

		private static readonly FieldRef<ItemCooking, Renderer[]> ItemCookingRenderersRef = AccessTools.FieldRefAccess<ItemCooking, Renderer[]>("renderers");

		private static readonly FieldRef<ItemCooking, Color[]> ItemCookingDefaultTintsRef = AccessTools.FieldRefAccess<ItemCooking, Color[]>("defaultTints");

		private static readonly FieldRef<ItemCooking, bool> ItemCookingSetupRef = AccessTools.FieldRefAccess<ItemCooking, bool>("setup");

		private static readonly ItemCookingIntMethod RunAdditionalCookingBehaviorsDelegate = AccessTools.MethodDelegate<ItemCookingIntMethod>(AccessTools.Method(typeof(ItemCooking), "RunAdditionalCookingBehaviors", (Type[])null, (Type[])null), (object)null, true);

		private static readonly ItemCookingIntMethod ChangeStatsCookedDelegate = AccessTools.MethodDelegate<ItemCookingIntMethod>(AccessTools.Method(typeof(ItemCooking), "ChangeStatsCooked", (Type[])null, (Type[])null), (object)null, true);

		private static readonly ItemCookingIntMethod CookVisuallyDelegate = AccessTools.MethodDelegate<ItemCookingIntMethod>(AccessTools.Method(typeof(ItemCooking), "CookVisually", (Type[])null, (Type[])null), (object)null, true);

		private static Color GetSafeTint(Material material)
		{
			//IL_0009: 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_003b: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material == (Object)null)
			{
				return Color.white;
			}
			if (material.HasProperty("_Tint"))
			{
				return material.GetColor("_Tint");
			}
			if (material.HasProperty("_BaseColor"))
			{
				return material.GetColor("_BaseColor");
			}
			if (material.HasProperty("_Color"))
			{
				return material.GetColor("_Color");
			}
			return Color.white;
		}

		private static void TryApplyTint(Material material, Color color)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)material != (Object)null && material.HasProperty("_Tint"))
			{
				material.SetColor("_Tint", color);
			}
		}

		private static Color[] CaptureDefaultTints(Renderer[] renderers)
		{
			//IL_0029: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			Color[] array = (Color[])(object)new Color[renderers.Length];
			for (int i = 0; i < renderers.Length; i++)
			{
				array[i] = (((Object)(object)renderers[i] == (Object)null) ? Color.white : GetSafeTint(renderers[i].material));
			}
			return array;
		}

		private static MeshRenderer[] GetBackpackSafeRenderers(BackpackOnBackVisuals instance)
		{
			MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren<MeshRenderer>();
			List<MeshRenderer> list = new List<MeshRenderer>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && !ItemPatch.IsMikuTransform(((Component)componentsInChildren[i]).transform))
				{
					list.Add(componentsInChildren[i]);
				}
			}
			return list.ToArray();
		}

		private static Renderer[] GetItemCookingSafeRenderers(ItemCooking instance)
		{
			List<Renderer> list = new List<Renderer>();
			MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren<MeshRenderer>();
			foreach (MeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && !ItemPatch.IsMikuTransform(((Component)val).transform))
				{
					list.Add((Renderer)(object)val);
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)instance).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if ((Object)(object)val2 != (Object)null && !ItemPatch.IsMikuTransform(((Component)val2).transform))
				{
					list.Add((Renderer)(object)val2);
				}
			}
			return list.ToArray();
		}

		[HarmonyPatch(typeof(BackpackOnBackVisuals), "InitRenderers")]
		[HarmonyPrefix]
		public static bool BackpackOnBackVisuals_InitRenderers_Prefix(BackpackOnBackVisuals __instance)
		{
			MeshRenderer[] backpackSafeRenderers = GetBackpackSafeRenderers(__instance);
			BackpackRenderersRef.Invoke(__instance) = backpackSafeRenderers;
			ref Color[] reference = ref BackpackDefaultTintsRef.Invoke(__instance);
			Renderer[] renderers = (Renderer[])(object)backpackSafeRenderers;
			reference = CaptureDefaultTints(renderers);
			return false;
		}

		[HarmonyPatch(typeof(BackpackOnBackVisuals), "CookVisually")]
		[HarmonyPrefix]
		public static bool BackpackOnBackVisuals_CookVisually_Prefix(BackpackOnBackVisuals __instance, int __0)
		{
			//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_0057: 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_005c: 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_0068: 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)
			MeshRenderer[] array = BackpackRenderersRef.Invoke(__instance) ?? Array.Empty<MeshRenderer>();
			Color[] array2 = BackpackDefaultTintsRef.Invoke(__instance) ?? Array.Empty<Color>();
			if (__0 <= 0)
			{
				return false;
			}
			Color cookColor = ItemCooking.GetCookColor(__0);
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i] == (Object)null))
				{
					Color val = ((i < array2.Length) ? array2[i] : Color.white);
					TryApplyTint(((Renderer)array[i]).material, val * cookColor);
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(ItemCooking), "UpdateCookedBehavior")]
		[HarmonyPrefix]
		public static bool ItemCooking_UpdateCookedBehavior_Prefix(ItemCooking __instance)
		{
			Item component = ((Component)__instance).GetComponent<Item>();
			if ((Object)(object)component == (Object)null)
			{
				return true;
			}
			IntItemData data = component.GetData<IntItemData>((DataEntryKey)1);
			if (data == null)
			{
				return true;
			}
			if (data.Value == 0)
			{
				data.Value = data.Value;
			}
			if (ItemCookingRenderersRef.Invoke(__instance) == null)
			{
				Array.Empty<Renderer>();
			}
			if (ItemCookingDefaultTintsRef.Invoke(__instance) == null)
			{
				Array.Empty<Color>();
			}
			_ = data.Value;
			CookVisuallyDelegate(__instance, data.Value);
			RunAdditionalCookingBehaviorsDelegate(__instance, data.Value);
			ChangeStatsCookedDelegate(__instance, data.Value);
			return false;
		}

		[HarmonyPatch(typeof(ItemCooking), "CookVisually")]
		[HarmonyPrefix]
		public static bool ItemCooking_CookVisually_Prefix(ItemCooking __instance, int __0)
		{
			//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_0061: 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_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] array = ItemCookingRenderersRef.Invoke(__instance) ?? Array.Empty<Renderer>();
			Color[] array2 = ItemCookingDefaultTintsRef.Invoke(__instance) ?? Array.Empty<Color>();
			if (__0 <= 0)
			{
				return false;
			}
			Color cookColor = ItemCooking.GetCookColor(__0);
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i] == (Object)null))
				{
					Material[] materials = array[i].materials;
					Color val = ((i < array2.Length) ? array2[i] : Color.white);
					for (int j = 0; j < materials.Length; j++)
					{
						TryApplyTint(materials[j], val * cookColor);
					}
				}
			}
			return false;
		}
	}
	internal sealed class RuntimeReplacementModel
	{
		internal string DisplayName { get; private set; }

		internal Mesh Mesh { get; private set; }

		internal Material[] Materials { get; private set; }

		internal Vector3 MeshLocalOffset { get; private set; }

		internal Vector3 RecommendedBaseScale { get; private set; }

		internal Texture2D PrimaryTexture { get; private set; }

		internal Texture2D IconTexture { get; private set; }

		internal Material PrimaryMaterial
		{
			get
			{
				if (Materials == null || Materials.Length == 0)
				{
					return null;
				}
				return Materials[0];
			}
		}

		internal RuntimeReplacementModel(string displayName, Mesh mesh, Material[] materials, Vector3 meshLocalOffset, Vector3 recommendedBaseScale, Texture2D primaryTexture, Texture2D iconTexture)
		{
			//IL_0034: 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)
			DisplayName = (string.IsNullOrEmpty(displayName) ? "MIKU" : displayName);
			Mesh = mesh;
			Materials = materials ?? Array.Empty<Material>();
			MeshLocalOffset = meshLocalOffset;
			RecommendedBaseScale = recommendedBaseScale;
			PrimaryTexture = primaryTexture;
			IconTexture = iconTexture;
		}

		internal GameObject Instantiate(string rootName)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//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_0032: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(string.IsNullOrEmpty(rootName) ? "BoxMiku_Visual" : rootName);
			GameObject val2 = new GameObject("RuntimeMesh");
			val2.transform.SetParent(val.transform, false);
			val2.transform.localPosition = MeshLocalOffset;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one;
			val2.AddComponent<MeshFilter>().sharedMesh = Mesh;
			((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterials = CreateMaterialsForRenderer((!((Object)(object)Mesh != (Object)null)) ? 1 : Mesh.subMeshCount);
			return val;
		}

		internal Material[] CreateMaterialsForRenderer(int subMeshCount)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, subMeshCount);
			if (Materials == null || Materials.Length == 0)
			{
				Material val = CreateFallbackMaterial();
				if ((Object)(object)val == (Object)null)
				{
					return Array.Empty<Material>();
				}
				Material[] array = (Material[])(object)new Material[num];
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = new Material(val);
				}
				return array;
			}
			Material[] array2 = (Material[])(object)new Material[num];
			for (int j = 0; j < num; j++)
			{
				Material val2 = Materials[Mathf.Min(j, Materials.Length - 1)];
				object obj = array2;
				int num2 = j;
				obj = (((Object)(object)val2 != (Object)null) ? ((object)new Material(val2)) : ((object)CreateFallbackMaterial()));
				((object[])obj)[num2] = obj;
			}
			return array2;
		}

		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_002d: 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_003e: Expected O, but got Unknown
			//IL_003f: Expected O, but got Unknown
			Shader val = RuntimePmxLoader.FindCompatibleShader();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Material val2 = new Material(val)
			{
				name = "BoxMiku_Fallback",
				color = Color.white,
				renderQueue = 2000
			};
			RuntimePmxLoader.ConfigureOpaqueSurface(val2);
			return val2;
		}
	}
	internal static class RuntimePmxLoader
	{
		private sealed class PmxMaterialInfo
		{
			internal string Name;

			internal string MainTexturePath;

			internal string ToonTexturePath;

			internal Color DiffuseColor;

			internal int SurfaceIndexCount;
		}

		private sealed class PmxHeader
		{
			internal Encoding TextEncoding;

			internal int AdditionalUvCount;

			internal int VertexIndexSize;

			internal int TextureIndexSize;

			internal int BoneIndexSize;
		}

		private const string PreferredModelFileName = "_箱MIKU(50cm).pmx";

		private static readonly Vector3 ReferenceVisibleSizeAtBaseScale = new Vector3(1.5852638f, 1.2168914f, 0.8999324f);

		private static readonly Vector3 ReferenceVisibleCenterAtBaseScale = new Vector3(0.0330699f, 0.06277876f, 0.09902591f);

		internal static RuntimeReplacementModel Load(string replacementRoot, ManualLogSource log)
		{
			try
			{
				if (string.IsNullOrEmpty(replacementRoot) || !Directory.Exists(replacementRoot))
				{
					return null;
				}
				string text = FindPmxPath(replacementRoot);
				if (string.IsNullOrEmpty(text))
				{
					return null;
				}
				return BuildRuntimeModel(text, log);
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogError((object)("Failed to load runtime PMX replacement: " + ex));
				}
				return null;
			}
		}

		private static string FindPmxPath(string replacementRoot)
		{
			string text = Path.Combine(replacementRoot, "_箱MIKU(50cm).pmx");
			if (File.Exists(text))
			{
				return text;
			}
			string[] files = Directory.GetFiles(replacementRoot, "*.pmx", SearchOption.TopDirectoryOnly);
			if (files.Length == 0)
			{
				return null;
			}
			return files[0];
		}

		private static RuntimeReplacementModel BuildRuntimeModel(string pmxPath, ManualLogSource log)
		{
			//IL_0072: 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_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)
			//IL_0090: 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)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			using FileStream input = File.OpenRead(pmxPath);
			using BinaryReader binaryReader = new BinaryReader(input);
			PmxHeader pmxHeader = ReadHeader(binaryReader);
			ReadText(binaryReader, pmxHeader.TextEncoding);
			ReadText(binaryReader, pmxHeader.TextEncoding);
			ReadText(binaryReader, pmxHeader.TextEncoding);
			ReadText(binaryReader, pmxHeader.TextEncoding);
			int num = binaryReader.ReadInt32();
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = ConvertPosition(ReadVector3(binaryReader));
				array2[i] = ConvertNormal(ReadVector3(binaryReader));
				array3[i] = ConvertUv(ReadVector2(binaryReader));
				SkipAdditionalUv(binaryReader, pmxHeader.AdditionalUvCount);
				SkipVertexWeight(binaryReader, pmxHeader.BoneIndexSize);
				binaryReader.ReadSingle();
			}
			int num2 = binaryReader.ReadInt32();
			int[] array4 = new int[num2];
			for (int j = 0; j < num2; j++)
			{
				array4[j] = ReadUnsignedIndex(binaryReader, pmxHeader.VertexIndexSize);
			}
			List<string> texturePaths = ReadTexturePaths(binaryReader, pmxHeader.TextEncoding, pmxPath);
			List<PmxMaterialInfo> materials = ReadMaterials(binaryReader, pmxHeader, texturePaths);
			Dictionary<string, Texture2D> textureCache = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);
			Texture2D primaryTexture;
			Texture2D iconTexture;
			Material[] materials2 = BuildMaterials(materials, textureCache, log, out primaryTexture, out iconTexture);
			Mesh val = BuildMesh(Path.GetFileNameWithoutExtension(pmxPath), array, array2, array3, array4, materials);
			Bounds bounds = val.bounds;
			Vector3 recommendedBaseScale = CalculateRecommendedBaseScale(((Bounds)(ref bounds)).size.y);
			Vector3 meshLocalOffset = CalculateMeshOffset(val.bounds, recommendedBaseScale);
			return new RuntimeReplacementModel("MIKU", val, materials2, meshLocalOffset, recommendedBaseScale, primaryTexture, iconTexture);
		}

		private static PmxHeader ReadHeader(BinaryReader reader)
		{
			string @string = Encoding.ASCII.GetString(reader.ReadBytes(4));
			if (!string.Equals(@string, "PMX ", StringComparison.Ordinal))
			{
				throw new InvalidDataException("Unsupported PMX signature: " + @string);
			}
			float num = reader.ReadSingle();
			if (num < 2f || num >= 3f)
			{
				throw new InvalidDataException("Unsupported PMX version: " + num);
			}
			byte count = reader.ReadByte();
			byte[] array = reader.ReadBytes(count);
			if (array.Length < 8)
			{
				throw new InvalidDataException("PMX header is incomplete.");
			}
			return new PmxHeader
			{
				TextEncoding = ((array[0] == 0) ? Encoding.Unicode : Encoding.UTF8),
				AdditionalUvCount = array[1],
				VertexIndexSize = array[2],
				TextureIndexSize = array[3],
				BoneIndexSize = array[5]
			};
		}

		private static string ReadText(BinaryReader reader, Encoding encoding)
		{
			int num = reader.ReadInt32();
			if (num <= 0)
			{
				return string.Empty;
			}
			byte[] bytes = reader.ReadBytes(num);
			return encoding.GetString(bytes);
		}

		private static void SkipAdditionalUv(BinaryReader reader, int additionalUvCount)
		{
			for (int i = 0; i < additionalUvCount; i++)
			{
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
			}
		}

		private static void SkipVertexWeight(BinaryReader reader, int boneIndexSize)
		{
			byte b = reader.ReadByte();
			switch (b)
			{
			case 0:
				ReadSignedIndex(reader, boneIndexSize);
				break;
			case 1:
				ReadSignedIndex(reader, boneIndexSize);
				ReadSignedIndex(reader, boneIndexSize);
				reader.ReadSingle();
				break;
			case 2:
			case 4:
			{
				for (int j = 0; j < 4; j++)
				{
					ReadSignedIndex(reader, boneIndexSize);
				}
				for (int k = 0; k < 4; k++)
				{
					reader.ReadSingle();
				}
				break;
			}
			case 3:
			{
				ReadSignedIndex(reader, boneIndexSize);
				ReadSignedIndex(reader, boneIndexSize);
				reader.ReadSingle();
				for (int i = 0; i < 9; i++)
				{
					reader.ReadSingle();
				}
				break;
			}
			default:
				throw new InvalidDataException("Unsupported PMX vertex deform type: " + b);
			}
		}

		private static List<string> ReadTexturePaths(BinaryReader reader, Encoding encoding, string pmxPath)
		{
			int num = reader.ReadInt32();
			List<string> list = new List<string>(num);
			string baseDirectory = Path.GetDirectoryName(pmxPath) ?? string.Empty;
			for (int i = 0; i < num; i++)
			{
				string relativePath = ReadText(reader, encoding);
				list.Add(ResolveRelativePath(baseDirectory, relativePath));
			}
			return list;
		}

		private static List<PmxMaterialInfo> ReadMaterials(BinaryReader reader, PmxHeader header, List<string> texturePaths)
		{
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			int num = reader.ReadInt32();
			List<PmxMaterialInfo> list = new List<PmxMaterialInfo>(num);
			Color diffuseColor = default(Color);
			for (int i = 0; i < num; i++)
			{
				string name = ReadText(reader, header.TextEncoding);
				ReadText(reader, header.TextEncoding);
				((Color)(ref diffuseColor))..ctor(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadByte();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				reader.ReadSingle();
				int index = ReadSignedIndex(reader, header.TextureIndexSize);
				ReadSignedIndex(reader, header.TextureIndexSize);
				reader.ReadByte();
				byte b = reader.ReadByte();
				int index2 = ((b == 0) ? ReadSignedIndex(reader, header.TextureIndexSize) : reader.ReadByte());
				ReadText(reader, header.TextEncoding);
				int surfaceIndexCount = reader.ReadInt32();
				list.Add(new PmxMaterialInfo
				{
					Name = name,
					MainTexturePath = GetTexturePath(texturePaths, index),
					ToonTexturePath = ((b == 0) ? GetTexturePath(texturePaths, index2) : null),
					DiffuseColor = diffuseColor,
					SurfaceIndexCount = surfaceIndexCount
				});
				_ = 0;
			}
			return list;
		}

		private static Material[] BuildMaterials(List<PmxMaterialInfo> materials, Dictionary<string, Texture2D> textureCache, ManualLogSource log, out Texture2D primaryTexture, out Texture2D iconTexture)
		{
			//IL_005c: 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_0063: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			primaryTexture = null;
			iconTexture = null;
			Shader val = FindCompatibleShader();
			Material[] array = (Material[])(object)new Material[Mathf.Max(1, materials.Count)];
			Dictionary<Texture2D, bool> transparencyCache = new Dictionary<Texture2D, bool>();
			for (int i = 0; i < array.Length; i++)
			{
				PmxMaterialInfo pmxMaterialInfo = ((i < materials.Count) ? materials[i] : null);
				Material val2 = (((Object)(object)val != (Object)null) ? ne