Decompiled source of ScallionMiku v1.0.1

plugins/ScallionMiku.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
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;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("ScallionMiku")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.0.0")]
[assembly: AssemblyInformationalVersion("0.4.0")]
[assembly: AssemblyProduct("ScallionMiku")]
[assembly: AssemblyTitle("ScallionMiku")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.4.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 ScallionMiku
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("com.github.Thanks.ScallionMiku", "ScallionMiku", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		private const float LiveConfigRefreshInterval = 0.03f;

		private static readonly string[] LegacyPluginIds = new string[2] { "com.github.Thanks.MikuBongFix", "com.github.FelineEntity.MikuBongFix" };

		private const string BundleFileName = "ScallionMiku";

		private const string ExternalIconFileName = "ScallionMikuUI.png";

		private const string PrefabAssetPath = "assets/葱音未来_by_翼月生/scallionmiku.prefab";

		private const string MaterialAssetPath = "assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat";

		private const string IconTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png";

		private const string MainTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png";

		private const string ConfigSection = "Main";

		private const string WorldScaleConfigKey = "Fufu Size In World";

		private const string BackpackModelScaleConfigKey = "Backpack Model Scale";

		private const string LegacyFufuBackpackScaleConfigKey = "Fufu Size In Backpack";

		private const string LegacyMikuBackpackScaleConfigKey = "Miku Size In Backpack";

		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 PositionOffsetMin = -2f;

		private const float PositionOffsetMax = 2f;

		private const float DefaultWorldScaleMultiplier = 0.9f;

		private const float DefaultBackpackScaleMultiplier = 0.4f;

		private const string DefaultExpressionName = "None";

		private const float DefaultExpressionWeight = 1f;

		private const float RuntimeScaleAdjustment = 0.78f;

		private const float BaseScaleMultiplier = 1.5f;

		private const int CurrentConfigVersion = 1;

		private const float BundledBaseScaleMin = 0.04f;

		private const float BundledBaseScaleMax = 1.2f;

		private static readonly string[] ExpressionOptions = new string[16]
		{
			"None", "笑い", "まばたき", "ウィンク", "ウィンク右", "ウィンク2", "ウィンク2右", "あ", "い", "う",
			"え", "お", "あ2", "口角上げ", "口角下げ", "はぅ"
		};

		private static readonly Vector3 DefaultBundledReplacementBaseScale = new Vector3(0.52f, 0.52f, 0.52f);

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

		private static readonly Vector3 DefaultPositionOffset = Vector3.zero;

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

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

		private static readonly string[] MaterialNameHints = new string[3] { "scallionmiku-8.shintai", "shintai", "miku" };

		private static readonly string[] IconTextureNameHints = new string[4] { "身体", "shintai", "miku", "scallionmiku" };

		private static readonly string[] MainTextureNameHints = new string[5] { "身体", "shintai", "miku", "scallionmiku", "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 ConfigEntry<float> _positionOffsetX;

		private static ConfigEntry<float> _positionOffsetY;

		private static ConfigEntry<float> _positionOffsetZ;

		private static ConfigEntry<string> _expressionName;

		private static ConfigEntry<int> _configVersion;

		private bool _liveConfigStateInitialized;

		private bool _lastObservedModEnabled;

		private float _lastObservedWorldScale;

		private float _lastObservedBackpackScale;

		private Vector3 _lastObservedPositionOffset;

		private string _lastObservedExpressionName;

		private bool _pendingLiveConfigRefresh;

		private float _nextLiveConfigRefreshTime;

		private bool _liveConfigEventsBound;

		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 Vector3 _bundledReplacementBaseScale = DefaultBundledReplacementBaseScale;

		private static RuntimeReplacementModel _runtimeReplacementModel;

		public const string Name = "ScallionMiku";

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

		public const string Version = "1.0.0";

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

		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 => RuntimeReplacementModel == null;

		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 DefaultWorldScaleSetting => 0.9f;

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

		internal static float DefaultBackpackScaleSetting => 0.4f;

		internal static Vector3 ReplacementBaseScale
		{
			get
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if (RuntimeReplacementModel == null)
				{
					return _bundledReplacementBaseScale * 0.78f * 1.5f;
				}
				return RuntimeReplacementModel.RecommendedBaseScale * 0.78f * 1.5f;
			}
		}

		internal static Vector3 PositionOffset => new Vector3((_positionOffsetX == null) ? DefaultPositionOffset.x : Mathf.Clamp(_positionOffsetX.Value, -2f, 2f), (_positionOffsetY == null) ? DefaultPositionOffset.y : Mathf.Clamp(_positionOffsetY.Value, -2f, 2f), (_positionOffsetZ == null) ? DefaultPositionOffset.z : Mathf.Clamp(_positionOffsetZ.Value, -2f, 2f));

		internal static string ExpressionName
		{
			get
			{
				string text = ((_expressionName == null) ? "None" : (_expressionName.Value ?? "None").Trim());
				if (!string.IsNullOrEmpty(text))
				{
					return text;
				}
				return "None";
			}
		}

		internal static float ExpressionWeight => 1f;

		internal static string ReplacementDisplayName => "Miku";

		internal static int ReplacementRefreshRevision { get; private set; } = 1;


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

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

		private void Update()
		{
			if (HasLiveConfigStateChanged())
			{
				CaptureLiveConfigState();
				_pendingLiveConfigRefresh = true;
			}
			if (_pendingLiveConfigRefresh && !(Time.realtimeSinceStartup < _nextLiveConfigRefreshTime))
			{
				RefreshReplacementInstancesNow();
			}
		}

		private bool HasLiveConfigStateChanged()
		{
			//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)
			if (!_liveConfigStateInitialized)
			{
				return true;
			}
			if (_lastObservedModEnabled != ModEnabled)
			{
				return true;
			}
			if (!Mathf.Approximately(_lastObservedWorldScale, WorldScaleMultiplier))
			{
				return true;
			}
			if (!Mathf.Approximately(_lastObservedBackpackScale, BackpackScaleMultiplier))
			{
				return true;
			}
			if (_lastObservedPositionOffset != PositionOffset)
			{
				return true;
			}
			return !string.Equals(_lastObservedExpressionName, ExpressionName, StringComparison.Ordinal);
		}

		private void CaptureLiveConfigState()
		{
			//IL_0022: 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)
			_lastObservedModEnabled = ModEnabled;
			_lastObservedWorldScale = WorldScaleMultiplier;
			_lastObservedBackpackScale = BackpackScaleMultiplier;
			_lastObservedPositionOffset = PositionOffset;
			_lastObservedExpressionName = ExpressionName;
			_liveConfigStateInitialized = true;
		}

		private void BindLiveConfigEvents()
		{
			if (!_liveConfigEventsBound)
			{
				BindLiveConfigEvent<bool>(_modEnabled);
				BindLiveConfigEvent<float>(_worldScaleMultiplier);
				BindLiveConfigEvent<float>(_backpackScaleMultiplier);
				BindLiveConfigEvent<float>(_positionOffsetX);
				BindLiveConfigEvent<float>(_positionOffsetY);
				BindLiveConfigEvent<float>(_positionOffsetZ);
				BindLiveConfigEvent<string>(_expressionName);
				_liveConfigEventsBound = true;
			}
		}

		private void BindLiveConfigEvent<T>(ConfigEntry<T> entry)
		{
			if (entry != null)
			{
				entry.SettingChanged -= OnLiveConfigSettingChanged;
				entry.SettingChanged += OnLiveConfigSettingChanged;
			}
		}

		private void OnLiveConfigSettingChanged(object sender, EventArgs args)
		{
			CaptureLiveConfigState();
			if (Time.realtimeSinceStartup >= _nextLiveConfigRefreshTime)
			{
				RefreshReplacementInstancesNow();
			}
			else
			{
				_pendingLiveConfigRefresh = true;
			}
		}

		private void RefreshReplacementInstancesNow()
		{
			_pendingLiveConfigRefresh = false;
			_nextLiveConfigRefreshTime = Time.realtimeSinceStartup + 0.03f;
			ReplacementRefreshRevision = ((ReplacementRefreshRevision == int.MaxValue) ? 1 : (ReplacementRefreshRevision + 1));
			Patch_AskRoutine.HandleModConfigStateChanged();
			ItemPatch.RefreshAllReplacementInstances();
		}

		private void MigrateLegacyConfigIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (string.IsNullOrEmpty(configFilePath) || File.Exists(configFilePath) || LegacyPluginIds == null)
				{
					return;
				}
				for (int i = 0; i < LegacyPluginIds.Length; i++)
				{
					string text = LegacyPluginIds[i];
					if (!string.IsNullOrEmpty(text))
					{
						string text2 = Path.Combine(Paths.ConfigPath, text + ".cfg");
						if (File.Exists(text2))
						{
							File.Copy(text2, configFilePath, overwrite: false);
							((BaseUnityPlugin)this).Config.Reload();
							VerboseLog("Migrated legacy config to: " + configFilePath);
							break;
						}
					}
				}
			}
			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
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Expected O, but got Unknown
			_modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Enable Fufu Replacement", true, new ConfigDescription("Master switch for the mod. When disabled, the original BingBong visuals, name, icon, and colliders are restored.", (AcceptableValueBase)null, Array.Empty<object>()));
			_worldScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Fufu Size In World", 0.9f, new ConfigDescription("Scale multiplier for Fufu while held or lying in the world.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 1.1f), Array.Empty<object>()));
			_backpackScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Backpack Model Scale", 0.4f, new ConfigDescription("Scale multiplier for the replacement model while the item is shown in the backpack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
			_positionOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset X", DefaultPositionOffset.x, new ConfigDescription("Extra local position offset on the X axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>()));
			_positionOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset Y", DefaultPositionOffset.y, new ConfigDescription("Extra local position offset on the Y axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>()));
			_positionOffsetZ = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset Z", DefaultPositionOffset.z, new ConfigDescription("Extra local position offset on the Z axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>()));
			_expressionName = ((BaseUnityPlugin)this).Config.Bind<string>("Main", "Face Expression", "None", new ConfigDescription("PMX facial expression morph name. Examples: None, 笑い, まばたき, ウィンク, ウィンク右, あ, い, う, え, お", (AcceptableValueBase)(object)new AcceptableValueList<string>(ExpressionOptions), Array.Empty<object>()));
			_configVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "Config Version", 1, new ConfigDescription("Internal migration marker for ScallionMiku.", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private void NormalizeMigratedScaleConfigIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (!string.IsNullOrEmpty(configFilePath) && File.Exists(configFilePath) && (FileContainsSetting(configFilePath, "Miku Size In World") || FileContainsSetting(configFilePath, "Fufu Size In Backpack") || FileContainsSetting(configFilePath, "Miku Size In Backpack") || FileContainsSetting(configFilePath, "Enable Miku Replacement")))
				{
					bool flag = false;
					if (TryReadFloatSetting(configFilePath, "Miku Size In World", out var value) && _worldScaleMultiplier != null && _worldScaleMultiplier.Value <= 0.4001f)
					{
						_worldScaleMultiplier.Value = Mathf.Clamp(value, 0.4f, 1.1f);
						flag = true;
					}
					if (!FileContainsSetting(configFilePath, "Backpack Model Scale") && TryReadFirstFloatSetting(configFilePath, out var value2, "Fufu Size In Backpack", "Miku Size In Backpack") && _backpackScaleMultiplier != null)
					{
						_backpackScaleMultiplier.Value = Mathf.Clamp(value2, 0.2f, 1f);
						flag = true;
					}
					if (flag)
					{
						((BaseUnityPlugin)this).Config.Save();
						VerboseLog("Normalized migrated ScallionMiku scale settings for current runtime model.");
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to normalize migrated config values: " + ex.Message));
			}
		}

		private static bool FileContainsSetting(string configPath, string key)
		{
			if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath))
			{
				return false;
			}
			string[] array = File.ReadAllLines(configPath);
			foreach (string text in array)
			{
				if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryReadFloatSetting(string configPath, string key, out float value)
		{
			value = 0f;
			if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath))
			{
				return false;
			}
			string[] array = File.ReadAllLines(configPath);
			foreach (string text in array)
			{
				if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal))
				{
					return float.TryParse(text.Substring((key + " =").Length).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out value);
				}
			}
			return false;
		}

		private static bool TryReadFirstFloatSetting(string configPath, out float value, params string[] keys)
		{
			value = 0f;
			if (keys == null || keys.Length == 0)
			{
				return false;
			}
			foreach (string key in keys)
			{
				if (TryReadFloatSetting(configPath, key, out value))
				{
					return true;
				}
			}
			return false;
		}

		private void NormalizePositionBaselineConfigIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (!string.IsNullOrEmpty(configFilePath) && File.Exists(configFilePath) && (!FileContainsSetting(configFilePath, "Config Version") || _configVersion == null || _configVersion.Value < 1))
				{
					if (_positionOffsetX != null)
					{
						_positionOffsetX.Value = DefaultPositionOffset.x;
					}
					if (_positionOffsetY != null)
					{
						_positionOffsetY.Value = DefaultPositionOffset.y;
					}
					if (_positionOffsetZ != null)
					{
						_positionOffsetZ.Value = DefaultPositionOffset.z;
					}
					if (_configVersion != null)
					{
						_configVersion.Value = 1;
					}
					((BaseUnityPlugin)this).Config.Save();
					VerboseLog("Reset model position offsets to zero for the new baseline anchor.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to normalize position baseline config values: " + ex.Message));
			}
		}

		private void LoadAssets()
		{
			//IL_0007: 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)
			Texture2D val = LoadExternalIconTexture();
			_bundledReplacementBaseScale = DefaultBundledReplacementBaseScale;
			string text = ResolveBundlePath();
			RuntimeReplacementModel = null;
			Bundle = null;
			MochiPrefab = null;
			MochiMaterial = null;
			MochiTexture = val;
			MikuMainTexture = null;
			RuntimeMikuMaterial = null;
			if (File.Exists(text))
			{
				if (!TryLoadReplacementBundle(text, val))
				{
					Log.LogError((object)("Found ScallionMiku bundle but failed to initialize replacement from: " + text));
				}
			}
			else
			{
				Log.LogError((object)("ScallionMiku bundle is missing. Bundle-only runtime is enabled, so no PMX fallback will be loaded: " + text));
			}
		}

		private bool TryLoadReplacementBundle(string bundlePath, Texture2D externalIconTexture)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			Bundle = AssetBundle.LoadFromFile(bundlePath);
			if ((Object)(object)Bundle == (Object)null)
			{
				Log.LogError((object)("Failed to load ScallionMiku AssetBundle: " + bundlePath));
				return false;
			}
			RuntimeReplacementModel = null;
			MochiPrefab = LoadBundleAssetWithFallback<GameObject>("assets/葱音未来_by_翼月生/scallionmiku.prefab", PrefabNameHints);
			MochiMaterial = LoadBundleAssetWithFallback<Material>("assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat", MaterialNameHints);
			MochiTexture = externalIconTexture ?? LoadBundleAssetWithFallback<Texture2D>("assets/葱音未来_by_翼月生/textures/身体.png", IconTextureNameHints);
			Texture2D val = LoadBundleAssetWithFallback<Texture2D>("assets/葱音未来_by_翼月生/textures/身体.png", MainTextureNameHints);
			MikuMainTexture = CreateReadableTexture(val) ?? val;
			if ((Object)(object)MochiPrefab == (Object)null)
			{
				Log.LogError((object)"Failed to load replacement prefab from asset bundle.");
				Bundle.Unload(false);
				Bundle = null;
				return false;
			}
			_bundledReplacementBaseScale = CalculateBundledReplacementBaseScale(MochiPrefab);
			ConfigureMochiMaterial(MikuMainTexture);
			RuntimeMikuMaterial = CreateRuntimeMikuMaterial(MikuMainTexture);
			ItemPatch.SanitizeLoadedPrefabRendererMaterials(MochiPrefab, "TryLoadReplacementBundle");
			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.");
			}
			VerboseLog("Loaded ScallionMiku replacement from asset bundle: " + bundlePath);
			return true;
		}

		private static Vector3 CalculateBundledReplacementBaseScale(GameObject prefab)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)prefab == (Object)null)
			{
				return DefaultBundledReplacementBaseScale;
			}
			Vector3 val;
			if (!TryCalculatePrefabBounds(prefab.transform, out var combinedBounds, out var rendererCount))
			{
				ManualLogSource log = Log;
				val = DefaultBundledReplacementBaseScale;
				log.LogWarning((object)("Failed to calculate bundled prefab bounds. Falling back to default bundle base scale: " + ((Vector3)(ref val)).ToString("F4")));
				return DefaultBundledReplacementBaseScale;
			}
			float num = Mathf.Max(((Bounds)(ref combinedBounds)).size.y, 0.0001f);
			float num2 = RuntimeReferenceVisibleSizeAtBaseScale.y * 0.78f * 1.5f;
			float num3 = Mathf.Clamp(num2 / num, 0.04f, 1.2f);
			Vector3 result = default(Vector3);
			((Vector3)(ref result))..ctor(num3, num3, num3);
			string[] obj = new string[8]
			{
				"Auto-calculated ScallionMiku bundle base scale. rendererCount=",
				rendererCount.ToString(CultureInfo.InvariantCulture),
				", prefabBoundsSize=",
				null,
				null,
				null,
				null,
				null
			};
			val = ((Bounds)(ref combinedBounds)).size;
			obj[3] = ((Vector3)(ref val)).ToString("F4");
			obj[4] = ", targetHeight=";
			obj[5] = num2.ToString("F4", CultureInfo.InvariantCulture);
			obj[6] = ", baseScale=";
			obj[7] = ((Vector3)(ref result)).ToString("F4");
			VerboseLog(string.Concat(obj));
			return result;
		}

		private static bool TryCalculatePrefabBounds(Transform root, out Bounds combinedBounds, out int rendererCount)
		{
			//IL_0001: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			combinedBounds = default(Bounds);
			rendererCount = 0;
			if ((Object)(object)root == (Object)null)
			{
				return false;
			}
			bool hasBounds = false;
			Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix;
			MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>(true);
			foreach (MeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
					if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
					{
						AppendTransformedBounds(worldToLocalMatrix, ((Component)val).transform.localToWorldMatrix, component.sharedMesh.bounds, ref combinedBounds, ref hasBounds);
						rendererCount++;
					}
				}
			}
			SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sharedMesh == (Object)null))
				{
					Bounds localBounds = ((Renderer)val2).localBounds;
					Vector3 size = ((Bounds)(ref localBounds)).size;
					Bounds sourceBounds = ((((Vector3)(ref size)).sqrMagnitude > 1E-06f) ? ((Renderer)val2).localBounds : val2.sharedMesh.bounds);
					AppendTransformedBounds(worldToLocalMatrix, ((Component)val2).transform.localToWorldMatrix, sourceBounds, ref combinedBounds, ref hasBounds);
					rendererCount++;
				}
			}
			return hasBounds;
		}

		private static void AppendTransformedBounds(Matrix4x4 rootWorldToLocal, Matrix4x4 childLocalToWorld, Bounds sourceBounds, ref Bounds combinedBounds, ref bool hasBounds)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//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_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0026: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 val = rootWorldToLocal * childLocalToWorld;
			Vector3 center = ((Bounds)(ref sourceBounds)).center;
			Vector3 extents = ((Bounds)(ref sourceBounds)).extents;
			for (int i = -1; i <= 1; i += 2)
			{
				for (int j = -1; j <= 1; j += 2)
				{
					for (int k = -1; k <= 1; k += 2)
					{
						Vector3 val2 = center + Vector3.Scale(extents, new Vector3((float)i, (float)j, (float)k));
						Vector3 val3 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val2);
						if (!hasBounds)
						{
							combinedBounds = new Bounds(val3, Vector3.zero);
							hasBounds = true;
						}
						else
						{
							((Bounds)(ref combinedBounds)).Encapsulate(val3);
						}
					}
				}
			}
		}

		private static string ResolveBundlePath()
		{
			return Path.Combine(directory, "ScallionMiku");
		}

		private Texture2D LoadExternalIconTexture()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00e2: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(directory, "ScallionMikuUI.png");
			if (!File.Exists(text))
			{
				return null;
			}
			try
			{
				using FileStream fileStream = File.OpenRead(text);
				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(text)
					};
					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 external icon texture '" + text + "': " + 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)
						{
							VerboseLog("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)
			{
				VerboseLog("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.3f);
				}
				if (material.HasProperty("_Glossiness"))
				{
					material.SetFloat("_Glossiness", 0.3f);
				}
				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 = "Miku_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
	{
		public bool HasAppliedState;

		public int LastRefreshRevision = -1;

		public int LastLayer = int.MinValue;

		public ItemState LastItemState;

		public bool LastShouldShow;

		public bool HiddenByOriginalRule;

		public Vector3 LastLocalPosition;

		public Quaternion LastLocalRotation = Quaternion.identity;

		public Vector3 LastLocalScale;
	}
	public class MikuCollisionMarker : MonoBehaviour
	{
	}
	public class MikuTwinTailClothState : MonoBehaviour
	{
		public int MeshInstanceId;

		public int MovableVertexCount;
	}
	public class MikuScaleRefreshGuard : MonoBehaviour
	{
		private bool _pendingRefresh;

		private bool _hardReset;

		private int _targetFrame = -1;

		private bool _clothSuspendedForPause;

		public void QueueRefresh(bool hardReset)
		{
			_pendingRefresh = true;
			_hardReset |= hardReset;
			_targetFrame = Mathf.Max(_targetFrame, Time.frameCount + 1);
		}

		private void LateUpdate()
		{
			bool flag = Time.timeScale <= 0.0001f;
			if (flag)
			{
				SuspendClothsForPause();
			}
			else if (_clothSuspendedForPause)
			{
				ResumeClothsAfterPause();
			}
			if (_pendingRefresh && Time.frameCount >= _targetFrame)
			{
				_pendingRefresh = false;
				_targetFrame = -1;
				RefreshSkinnedMeshes();
				RefreshCloths(_hardReset || flag);
				_hardReset = false;
			}
		}

		private void RefreshSkinnedMeshes()
		{
			//IL_0059: 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_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				val.updateWhenOffscreen = true;
				Vector3 size;
				Bounds val2;
				if ((Object)(object)val.sharedMesh != (Object)null)
				{
					Bounds bounds = val.sharedMesh.bounds;
					size = ((Bounds)(ref bounds)).size;
					if (((Vector3)(ref size)).sqrMagnitude > 1E-06f)
					{
						val2 = val.sharedMesh.bounds;
						goto IL_006b;
					}
				}
				val2 = ((Renderer)val).localBounds;
				goto IL_006b;
				IL_006b:
				Bounds localBounds = val2;
				size = ((Bounds)(ref localBounds)).size;
				if (((Vector3)(ref size)).sqrMagnitude > 1E-06f)
				{
					((Bounds)(ref localBounds)).Expand(new Vector3(0.2f, 0.25f, 0.2f));
					((Renderer)val).localBounds = localBounds;
				}
			}
		}

		private void RefreshCloths(bool hardReset)
		{
			Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true);
			foreach (Cloth val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				val.ClearTransformMotion();
				if (hardReset && val.enabled)
				{
					val.enabled = false;
					if (!_clothSuspendedForPause)
					{
						val.enabled = true;
					}
				}
				val.ClearTransformMotion();
			}
		}

		private void SuspendClothsForPause()
		{
			Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true);
			foreach (Cloth val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.ClearTransformMotion();
					if (val.enabled)
					{
						val.enabled = false;
					}
				}
			}
			_clothSuspendedForPause = true;
		}

		private void ResumeClothsAfterPause()
		{
			RefreshSkinnedMeshes();
			Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true);
			foreach (Cloth val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.enabled = true;
					val.ClearTransformMotion();
				}
			}
			_clothSuspendedForPause = false;
		}
	}
	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;

		internal Item BoundItem => _boundItem;

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

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

		public void SetRootTarget(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			_rootLocalPosition = rootLocalPosition;
			_rootLocalRotation = rootLocalRotation;
			_rootLocalScale = rootLocalScale;
		}

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

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

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

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

		public void Capture()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			_allTransforms = ((Component)this).GetComponentsInChildren<Transform>(true);
			_initialChildScales = (Vector3[])(object)new Vector3[_allTransforms.Length];
			for (int i = 0; i < _allTransforms.Length; i++)
			{
				_initialChildScales[i] = _allTransforms[i].localScale;
			}
		}

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

		private float _nextRefreshTime;

		private Item _boundItem;

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

		internal Item BoundItem => _boundItem;

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

		private void LateUpdate()
		{
			if (!Plugin.ModEnabled || !Plugin.EnableVisibilityGuard)
			{
				return;
			}
			MikuMarker component = ((Component)this).GetComponent<MikuMarker>();
			if ((Object)(object)component != (Object)null && component.HiddenByOriginalRule)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup < _nextRefreshTime)
			{
				return;
			}
			_nextRefreshTime = realtimeSinceStartup + 0.1f;
			if (!((Component)this).gameObject.activeSelf)
			{
				((Component)this).gameObject.SetActive(true);
			}
			int num = (((Object)(object)_boundItem != (Object)null) ? ((Component)_boundItem).gameObject.layer : ((Component)this).gameObject.layer);
			if (((Component)this).gameObject.layer != num)
			{
				((Component)this).gameObject.layer = num;
			}
			Renderer[] renderableChildren = GetRenderableChildren();
			foreach (Renderer val in renderableChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					EnsureRendererVisible(val, num);
				}
			}
		}

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

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

		private static void EnsureRendererVisible(Renderer renderer, int targetLayer)
		{
			if (!((Component)renderer).gameObject.activeSelf)
			{
				((Component)renderer).gameObject.SetActive(true);
			}
			if (renderer.forceRenderingOff)
			{
				renderer.forceRenderingOff = false;
			}
			if (!renderer.enabled)
			{
				renderer.enabled = true;
			}
			renderer.SetPropertyBlock((MaterialPropertyBlock)null);
			((Component)renderer).gameObject.layer = targetLayer;
			renderer.allowOcclusionWhenDynamic = false;
			ItemPatch.NormalizeRuntimeRendererMaterials(renderer, "RendererGuard");
		}

		private static void NormalizeRendererMaterialColor(Renderer renderer)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			Material[] sharedMaterials = renderer.sharedMaterials;
			foreach (Material val in sharedMaterials)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Color white = Color.white;
					if (val.HasProperty("_Tint"))
					{
						val.SetColor("_Tint", white);
					}
					if (val.HasProperty("_BaseColor"))
					{
						val.SetColor("_BaseColor", white);
					}
					if (val.HasProperty("_Color"))
					{
						val.SetColor("_Color", white);
					}
				}
			}
		}
	}
	[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 = "MikuFumo_Visual";

		private const string MikuCollisionName = "MikuCollisionProxy";

		private static readonly Vector3 BaselineMikuLocalPosition = new Vector3(-0.06f, -0.5f, 0f);

		private static readonly Vector3 WorldMikuLocalPosition = BaselineMikuLocalPosition;

		private static readonly Quaternion WorldMikuLocalRotation = Quaternion.identity;

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

		private static readonly Vector3 HeldMikuLocalPosition = BaselineMikuLocalPosition;

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

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

		private const int TwinTailChainStartIndex = 3;

		private const int TwinTailChainEndIndex = 9;

		private const int TwinTailAnchorIndex = 2;

		private const float TwinTailMinInfluenceThreshold = 0.12f;

		private const float TwinTailMaxDistanceCap = 0.78f;

		private const float TwinTailStretchingStiffness = 0.98f;

		private const float TwinTailBendingStiffness = 0.9f;

		private const float TwinTailDamping = 0.2f;

		private const float TwinTailFriction = 0.2f;

		private const float TwinTailCollisionMassScale = 0.06f;

		private const float TwinTailSolverFrequency = 36f;

		private const float TwinTailWorldVelocityScale = 0.2f;

		private const float TwinTailWorldAccelerationScale = 0.75f;

		private const double SlowCreateProfileTotalThresholdMs = 12.0;

		private const double SlowCreateProfileStageThresholdMs = 4.0;

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

		private static readonly string[] CollisionExcludedRendererKeywords = new string[8] { "hair", "tail", "twintail", "twin_tail", "pigtail", "ponytail", "bang", "ahoge" };

		private static readonly FieldRef<Character, CharacterData> CharacterDataRef = AccessTools.FieldRefAccess<Character, CharacterData>("data");

		private static readonly FieldRef<CharacterData, Item> CharacterCurrentItemRef = AccessTools.FieldRefAccess<CharacterData, Item>("_currentitem");

		private static readonly HashSet<int> LoggedRuntimeRendererMaterialWarnings = new HashSet<int>();

		private static bool SlowCreateProfileLogged;

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

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

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

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

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

		private static bool IsReplacementHiddenByOriginal(Item item)
		{
			return IsReplacementHiddenByOriginal(FindMikuRoot(item));
		}

		private static bool IsReplacementHiddenByOriginal(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return false;
			}
			MikuMarker component = ((Component)mikuRoot).GetComponent<MikuMarker>();
			if ((Object)(object)component != (Object)null)
			{
				return component.HiddenByOriginalRule;
			}
			return false;
		}

		private static void SetReplacementHiddenByOriginal(Transform mikuRoot, bool hidden)
		{
			if (!((Object)(object)mikuRoot == (Object)null))
			{
				MikuMarker component = ((Component)mikuRoot).GetComponent<MikuMarker>();
				if ((Object)(object)component != (Object)null)
				{
					component.HiddenByOriginalRule = hidden;
				}
			}
		}

		private static void HideReplacementForOriginalRule(Item item, Transform mikuRoot)
		{
			if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null))
			{
				SetReplacementHiddenByOriginal(mikuRoot, hidden: true);
				Transform val = FindMikuCollisionRoot(item);
				SetColliderArrayEnabled(((Object)(object)val != (Object)null) ? GetUsableProxyColliders(val) : Array.Empty<Collider>(), enabled: false);
				DisableOriginalColliders(item);
				RestoreOriginalItemRendererRefs(item);
				if (((Component)mikuRoot).gameObject.activeSelf)
				{
					((Component)mikuRoot).gameObject.SetActive(false);
				}
			}
		}

		private static Vector3 ResolveScaleByState(Item item)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			float num = (IsInBackpack(item) ? 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 bool UseBundledPositiveFacing()
		{
			return Plugin.RuntimeReplacementModel == null;
		}

		private static Vector3 CompensateRuntimeScalePosition(Vector3 basePosition, Vector3 currentScale, Vector3 referenceScale)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return basePosition;
		}

		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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: 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_0122: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_00a0: 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_0078: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = ResolveScaleByState(item);
			if (IsHeld(item))
			{
				bool flag = UseBundledPositiveFacing();
				localRotation = (flag ? BundledHeldMikuLocalRotation : HeldMikuLocalRotation);
				localScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val));
				Vector3 val2 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting;
				Vector3 referenceScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z)) : ApplyPlayerFacingScale(val2));
				localPosition = CompensateRuntimeScalePosition(HeldMikuLocalPosition, localScale, referenceScale);
			}
			else if (IsInBackpack(item))
			{
				localRotation = WorldMikuLocalRotation;
				localScale = val;
				Vector3 referenceScale2 = Plugin.ReplacementBaseScale * Plugin.DefaultBackpackScaleSetting;
				localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale2);
			}
			else
			{
				bool flag2 = UseBundledPositiveFacing();
				localRotation = (flag2 ? BundledWorldMikuLocalRotation : WorldMikuLocalRotation);
				localScale = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val));
				Vector3 val3 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting;
				Vector3 referenceScale3 = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val3.x), Mathf.Abs(val3.y), Mathf.Abs(val3.z)) : ApplyPlayerFacingScale(val3));
				localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale3);
			}
			localPosition += Plugin.PositionOffset;
		}

		private static Transform FindMikuRoot(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)item).transform.Find("MikuFumo_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 Transform FindMikuCollisionRoot(Item item)
		{
			if ((Object)(object)item == (Object)null)
			{
				return null;
			}
			Transform val = ((Component)item).transform.Find("MikuCollisionProxy");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			MikuCollisionMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren<MikuCollisionMarker>(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 MikuExpressionController FindExpressionController(Transform mikuRoot)
		{
			if (!((Object)(object)mikuRoot != (Object)null))
			{
				return null;
			}
			return ((Component)mikuRoot).GetComponentInChildren<MikuExpressionController>(true);
		}

		private static Item FindBoundItemFromMikuRoot(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return null;
			}
			MikuRendererGuard component = ((Component)mikuRoot).GetComponent<MikuRendererGuard>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.BoundItem != (Object)null)
			{
				return component.BoundItem;
			}
			MikuDeformGuard component2 = ((Component)mikuRoot).GetComponent<MikuDeformGuard>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)component2.BoundItem != (Object)null)
			{
				return component2.BoundItem;
			}
			MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot);
			if ((Object)(object)mikuExpressionController != (Object)null && (Object)(object)mikuExpressionController.BoundItem != (Object)null)
			{
				return mikuExpressionController.BoundItem;
			}
			return ((Component)mikuRoot).GetComponentInParent<Item>();
		}

		private static MikuScaleRefreshGuard EnsureScaleRefreshGuard(Transform mikuRoot)
		{
			if ((Object)(object)mikuRoot == (Object)null)
			{
				return null;
			}
			MikuScaleRefreshGuard mikuScaleRefreshGuard = ((Component)mikuRoot).GetComponent<MikuScaleRefreshGuard>();
			if ((Object)(object)mikuScaleRefreshGuard == (Object)null)
			{
				mikuScaleRefreshGuard = ((Component)mikuRoot).gameObject.AddComponent<MikuScaleRefreshGuard>();
			}
			return mikuScaleRefreshGuard;
		}

		private static void QueueScaleSensitiveRefresh(Transform mikuRoot, bool forceHardReset)
		{
			MikuScaleRefreshGuard mikuScaleRefreshGuard = EnsureScaleRefreshGuard(mikuRoot);
			if (!((Object)(object)mikuScaleRefreshGuard == (Object)null))
			{
				bool flag = Time.timeScale <= 0.0001f;
				mikuScaleRefreshGuard.QueueRefresh(forceHardReset || flag);
			}
		}

		private static MikuExpressionController EnsureExpressionController(Transform mikuRoot)
		{
			MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot);
			if ((Object)(object)mikuExpressionController != (Object)null || (Object)(object)mikuRoot == (Object)null)
			{
				return mikuExpressionController;
			}
			SkinnedMeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true);
			List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>();
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && val.sharedMesh.blendShapeCount > 0)
				{
					list.Add(val);
				}
			}
			if (list.Count > 0)
			{
				MikuExpressionController mikuExpressionController2 = ((Component)mikuRoot).gameObject.AddComponent<MikuExpressionController>();
				mikuExpressionController2.Initialize((IEnumerable<SkinnedMeshRenderer>)list);
				return mikuExpressionController2;
			}
			return null;
		}

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

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

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

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

		private static void ApplyMikuTextureSafe(Material material, Texture mikuTexture)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null) && !((Object)(object)mikuTexture == (Object)null))
			{
				if (TrySetTextureSafe(material, "_BaseMap", mikuTexture))
				{
					TrySetTextureTransformSafe(material, "_BaseMap", Vector2.one, Vector2.zero);
				}
				if (TrySetTextureSafe(material, "_MainTex", mikuTexture))
				{
					TrySetTextureTransformSafe(material, "_MainTex", Vector2.one, Vector2.zero);
				}
			}
		}

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

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

		private static void ApplyRealisticMaterialTuning(Material material)
		{
			//IL_000b: 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_0030: 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_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				Color val = ResolveMaterialTint(material);
				val.a = 1f;
				if (material.HasProperty("_Tint"))
				{
					material.SetColor("_Tint", val);
				}
				if (material.HasProperty("_BaseColor"))
				{
					material.SetColor("_BaseColor", val);
				}
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", val);
				}
				if (material.HasProperty("_Smoothness"))
				{
					material.SetFloat("_Smoothness", 0.3f);
				}
				if (material.HasProperty("_Glossiness"))
				{
					material.SetFloat("_Glossiness", 0.3f);
				}
				if (material.HasProperty("_Metallic"))
				{
					material.SetFloat("_Metallic", 0f);
				}
				if (material.HasProperty("_BumpScale"))
				{
					material.SetFloat("_BumpScale", 0f);
				}
				if (material.HasProperty("_OcclusionStrength"))
				{
					material.SetFloat("_OcclusionStrength", 0f);
				}
				if (material.HasProperty("_SpecularHighlights"))
				{
					material.SetFloat("_SpecularHighlights", 0f);
				}
				if (material.HasProperty("_EnvironmentReflections"))
				{
					material.SetFloat("_EnvironmentReflections", 0f);
				}
				DisableOptionalSurfaceTextures(material);
				if (material.HasProperty("_EmissionColor"))
				{
					material.SetColor("_EmissionColor", Color.black);
					material.DisableKeyword("_EMISSION");
				}
			}
		}

		private static Material CreateFallbackMaterial()
		{
			//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_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: 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)
			{
				return null;
			}
			return new Material(val)
			{
				color = Color.white
			};
		}

		private static Color ResolveMaterialTint(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 MikuMaterialTint;
			}
			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 MikuMaterialTint;
		}

		private static void OptimizeMaterialTextureSampling(Material material)
		{
			OptimizeTextureSampling(TryGetTexture(material));
		}

		private static Material CreateRendererMaterialInstance(Material template = null)
		{
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			template = template ?? Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial;
			bool flag = Plugin.RuntimeReplacementModel == null;
			if ((Object)(object)template == (Object)null)
			{
				Material val = CreateFallbackMaterial();
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				template = val;
			}
			Material val2;
			if (flag)
			{
				val2 = new Material(template);
				if ((Object)(object)val2.shader == (Object)null || !val2.shader.isSupported)
				{
					Material val3 = CreateFallbackMaterial();
					if ((Object)(object)val3 != (Object)null)
					{
						Texture obj = TryGetTexture(template);
						Texture mikuTexture = GetMikuTexture();
						if (obj == null)
						{
							obj = mikuTexture;
						}
						Texture val4 = obj;
						Color val5 = ResolveMaterialTint(template);
						val5.a = 1f;
						val2 = val3;
						if ((Object)(object)val4 != (Object)null)
						{
							OptimizeTextureSampling(val4);
							ApplyMikuTextureSafe(val2, val4);
						}
						if (val2.HasProperty("_Tint"))
						{
							val2.SetColor("_Tint", val5);
						}
						if (val2.HasProperty("_BaseColor"))
						{
							val2.SetColor("_BaseColor", val5);
						}
						if (val2.HasProperty("_Color"))
						{
							val2.SetColor("_Color", val5);
						}
					}
				}
			}
			else
			{
				val2 = new Material(template);
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			((Object)val2).name = (((Object)(object)template != (Object)null) ? ((Object)template).name : "MikuMaterial") + "_Runtime";
			Texture val6 = (((Object)(object)template != (Object)null) ? TryGetTexture(template) : TryGetTexture(val2));
			Texture mikuTexture2 = GetMikuTexture();
			if ((Object)(object)val6 != (Object)null)
			{
				OptimizeTextureSampling(val6);
				ApplyMikuTextureSafe(val2, val6);
			}
			else if ((Object)(object)mikuTexture2 != (Object)null)
			{
				OptimizeTextureSampling(mikuTexture2);
				ApplyMikuTextureSafe(val2, mikuTexture2);
			}
			Color val7 = ResolveMaterialTint(template);
			val7.a = 1f;
			if (val2.HasProperty("_Tint"))
			{
				val2.SetColor("_Tint", val7);
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", val7);
			}
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", val7);
			}
			DisableOptionalSurfaceTextures(val2);
			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("_SrcBlend"))
			{
				val2.SetFloat("_SrcBlend", 1f);
			}
			if (val2.HasProperty("_DstBlend"))
			{
				val2.SetFloat("_DstBlend", 0f);
			}
			if (val2.HasProperty("_Cull"))
			{
				val2.SetFloat("_Cull", 0f);
			}
			if (val2.HasProperty("_AlphaClip"))
			{
				val2.SetFloat("_AlphaClip", 0f);
			}
			if (val2.HasProperty("_Cutoff"))
			{
				val2.SetFloat("_Cutoff", 0f);
			}
			if (val2.HasProperty("_LOD"))
			{
				val2.SetFloat("_LOD", 600f);
			}
			val2.renderQueue = 2000;
			val2.SetOverrideTag("RenderType", "Opaque");
			val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT");
			val2.EnableKeyword("_SURFACE_TYPE_OPAQUE");
			val2.DisableKeyword("_ALPHATEST_ON");
			val2.DisableKeyword("_ALPHABLEND_ON");
			val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
			val2.DisableKeyword("LOD_FADE_CROSSFADE");
			ApplyRealisticMaterialTuning(val2);
			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 val = CreateRendererMaterialInstance((sourceMaterials != null && i < sourceMaterials.Length) ? sourceMaterials[i] : null);
				if ((Object)(object)val == (Object)null)
				{
					val = CreateFallbackMaterial();
				}
				if ((Object)(object)val != (Object)null)
				{
					Texture val2 = TryGetTexture(val);
					if ((Object)(object)val2 == (Object)null)
					{
						Texture mikuTexture = GetMikuTexture();
						if ((Object)(object)mikuTexture != (Object)null)
						{
							OptimizeTextureSampling(mikuTexture);
							ApplyMikuTextureSafe(val, mikuTexture);
						}
					}
					else
					{
						OptimizeTextureSampling(val2);
					}
					DisableOptionalSurfaceTextures(val);
					ApplyRealisticMaterialTuning(val);
				}
				array[i] = val;
			}
			return array;
		}

		private static Material ResolveRendererMaterialSlot(Material[] sourceMaterials, Material[] runtimeTemplateMaterials, int index, Material lastResolvedMaterial)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			Material val = ((sourceMaterials != null && index < sourceMaterials.Length) ? sourceMaterials[index] : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Material val2 = ((runtimeTemplateMaterials.Length != 0) ? runtimeTemplateMaterials[Mathf.Min(index, runtimeTemplateMaterials.Length - 1)] : null);
			Material val3 = CreateRendererMaterialInstance(val2);
			if ((Object)(object)val3 == (Object)null && (Object)(object)val2 != (Object)null)
			{
				val3 = new Material(val2);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
			if ((Object)(object)lastResolvedMaterial != (Object)null)
			{
				return lastResolvedMaterial;
			}
			Material val4 = Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial;
			if ((Object)(object)val4 != (Object)null)
			{
				val3 = CreateRendererMaterialInstance(val4);
				if ((Object)(object)val3 == (Object)null)
				{
					val3 = new Material(val4);
				}
			}
			return val3 ?? CreateFallbackMaterial();
		}

		private static Material[] NormalizeRuntimeMaterialArray(Material[] sourceMaterials, int subMeshCount)
		{
			int num = Mathf.Max(1, subMeshCount);
			Material[] array = (Material[])(object)new Material[num];
			Material[] runtimeTemplateMaterials = ((Plugin.RuntimeReplacementModel != null) ? Plugin.RuntimeReplacementModel.Materials : Array.Empty<Material>());
			Material lastResolvedMaterial = null;
			for (int i = 0; i < num; i++)
			{
				Material val = (array[i] = ResolveRendererMaterialSlot(sourceMaterials, runtimeTemplateMaterials, i, lastResolvedMaterial));
				if ((Object)(object)val != (Object)null)
				{
					lastResolvedMaterial = val;
				}
			}
			return array;
		}

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

		private static string GetTransformPath(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "<null>";
			}
			List<string> list = new List<string>();
			Transform val = transform;
			while ((Object)(object)val != (Object)null)
			{
				list.Add(((Object)val).name);
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list.ToArray());
		}

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

		internal static bool NormalizeRuntimeRendererMaterials(Renderer renderer, string context)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null)
			{
				return false;
			}
			int rendererSubMeshCount = GetRendererSubMeshCount(renderer);
			if (rendererSubMeshCount <= 0)
			{
				return false;
			}
			Material[] sharedMaterials;
			try
			{
				sharedMaterials = renderer.sharedMaterials;
			}
			catch (Exception ex)
			{
				Plugin.VerboseLog("[ItemPatch] Failed to inspect renderer materials at " + context + ": " + ex.Message);
				return false;
			}
			if (!ShouldNormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount))
			{
				return false;
			}
			int num = ((sharedMaterials != null) ? sharedMaterials.Length : 0);
			try
			{
				renderer.sharedMaterials = NormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount);
			}
			catch (Exception ex2)
			{
				Plugin.Log.LogWarning((object)("[ItemPatch] Failed to correct renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", error=" + ex2.Message));
				return false;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (val != null && (Object)(object)val.sharedMesh != (Object)null)
			{
				Bounds bounds = val.sharedMesh.bounds;
				((Bounds)(ref bounds)).Expand(0.5f);
				((Renderer)val).localBounds = bounds;
			}
			int instanceID = ((Object)renderer).GetInstanceID();
			if (!LoggedRuntimeRendererMaterialWarnings.Contains(instanceID) && Plugin.Log != null)
			{
				LoggedRuntimeRendererMaterialWarnings.Add(instanceID);
				Plugin.VerboseLog("[ItemPatch] Corrected runtime renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", type=" + ((object)renderer).GetType().Name + ", subMeshes=" + rendererSubMeshCount + ", sharedMaterials(before)=" + num + ", sharedMaterials(after)=" + renderer.sharedMaterials.Length);
			}
			return true;
		}

		internal static int NormalizeRuntimeRendererMaterials(Renderer[] renderers, string context)
		{
			if (renderers == null || renderers.Length == 0)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < renderers.Length; i++)
			{
				if (NormalizeRuntimeRendererMaterials(renderers[i], context))
				{
					num++;
				}
			}
			return num;
		}

		internal static void SanitizeLoadedPrefabRendererMaterials(GameObject prefabRoot, string context)
		{
			if (!((Object)(object)prefabRoot == (Object)null))
			{
				int num = NormalizeRuntimeRendererMaterials(prefabRoot.GetComponentsInChildren<Renderer>(true), context);
				if (num > 0)
				{
					Plugin.VerboseLog("[ItemPatch] Corrected " + num.ToString(CultureInfo.InvariantCulture) + " prefab renderer material layouts at " + context + " for " + ((