Decompiled source of ScallionMiku v1.0.3

plugins/ScallionMiku.dll

Decompiled 2 weeks 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.Bootstrap;
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("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[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("1.0.3.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.3")]
	public class Plugin : BaseUnityPlugin
	{
		private enum ConfigKey
		{
			ModEnabled,
			WorldScale,
			BackpackScale,
			PositionOffsetX,
			PositionOffsetY,
			PositionOffsetZ,
			FaceExpression
		}

		private enum FaceExpressionOption
		{
			None,
			Smile,
			Blink,
			Wink,
			WinkRight,
			Wink2,
			Wink2Right,
			A,
			I,
			U,
			E,
			O,
			A2,
			MouthCornerUp,
			MouthCornerDown,
			Hau
		}

		[CompilerGenerated]
		private sealed class <EnumerateCandidateTransforms>d__182 : IEnumerable<Transform>, IEnumerable, IEnumerator<Transform>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Transform <>2__current;

			private int <>l__initialThreadId;

			private object menuInstance;

			public object <>3__menuInstance;

			private Type menuType;

			public Type <>3__menuType;

			Transform IEnumerator<Transform>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnumerateCandidateTransforms>d__182(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				object? obj2;
				Transform val2;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					object obj = menuInstance;
					Component val = (Component)((obj is Component) ? obj : null);
					if (val != null)
					{
						<>2__current = val.transform;
						<>1__state = 1;
						return true;
					}
					goto IL_004d;
				}
				case 1:
					<>1__state = -1;
					goto IL_004d;
				case 2:
					{
						<>1__state = -1;
						break;
					}
					IL_004d:
					obj2 = menuType?.GetProperty("Content", InstanceFlags)?.GetValue(menuInstance);
					val2 = (Transform)((obj2 is Transform) ? obj2 : null);
					if (val2 != null)
					{
						<>2__current = val2;
						<>1__state = 2;
						return true;
					}
					break;
				}
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
			{
				<EnumerateCandidateTransforms>d__182 <EnumerateCandidateTransforms>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<EnumerateCandidateTransforms>d__ = this;
				}
				else
				{
					<EnumerateCandidateTransforms>d__ = new <EnumerateCandidateTransforms>d__182(0);
				}
				<EnumerateCandidateTransforms>d__.menuInstance = <>3__menuInstance;
				<EnumerateCandidateTransforms>d__.menuType = <>3__menuType;
				return <EnumerateCandidateTransforms>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Transform>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <EnumerateModConfigUiRoots>d__181 : IEnumerable<Transform>, IEnumerable, IEnumerator<Transform>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private Transform <>2__current;

			private int <>l__initialThreadId;

			private object menuInstance;

			public object <>3__menuInstance;

			private Type menuType;

			public Type <>3__menuType;

			private HashSet<int> <visited>5__2;

			private IEnumerator<Transform> <>7__wrap2;

			Transform IEnumerator<Transform>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <EnumerateModConfigUiRoots>d__181(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<visited>5__2 = null;
				<>7__wrap2 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<visited>5__2 = new HashSet<int>();
						<>7__wrap2 = EnumerateCandidateTransforms(menuInstance, menuType).GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap2.MoveNext())
					{
						Transform current = <>7__wrap2.Current;
						if ((Object)(object)current != (Object)null && <visited>5__2.Add(((Object)current).GetInstanceID()))
						{
							<>2__current = current;
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap2 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap2 != null)
				{
					<>7__wrap2.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
			{
				<EnumerateModConfigUiRoots>d__181 <EnumerateModConfigUiRoots>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<EnumerateModConfigUiRoots>d__ = this;
				}
				else
				{
					<EnumerateModConfigUiRoots>d__ = new <EnumerateModConfigUiRoots>d__181(0);
				}
				<EnumerateModConfigUiRoots>d__.menuInstance = <>3__menuInstance;
				<EnumerateModConfigUiRoots>d__.menuType = <>3__menuType;
				return <EnumerateModConfigUiRoots>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Transform>)this).GetEnumerator();
			}
		}

		[CompilerGenerated]
		private sealed class <GetAliasDefinitions>d__161 : IEnumerable<ConfigDefinition>, IEnumerable, IEnumerator<ConfigDefinition>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private ConfigDefinition <>2__current;

			private int <>l__initialThreadId;

			private ConfigKey configKey;

			public ConfigKey <>3__configKey;

			private string <canonicalKey>5__2;

			private string <localizedKey>5__3;

			private string <canonicalSection>5__4;

			private string <localizedSection>5__5;

			ConfigDefinition IEnumerator<ConfigDefinition>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <GetAliasDefinitions>d__161(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<canonicalKey>5__2 = null;
				<localizedKey>5__3 = null;
				<canonicalSection>5__4 = null;
				<localizedSection>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Expected O, but got Unknown
				//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Expected O, but got Unknown
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d5: Expected O, but got Unknown
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<canonicalKey>5__2 = GetConfigKeyName(configKey);
					<localizedKey>5__3 = GetKeyName(configKey, isChineseLanguage: true);
					<canonicalSection>5__4 = GetConfigSectionName(configKey);
					<localizedSection>5__5 = GetSectionName(configKey, isChineseLanguage: true);
					<>2__current = new ConfigDefinition(<canonicalSection>5__4, <canonicalKey>5__2);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					<>2__current = new ConfigDefinition(<canonicalSection>5__4, <localizedKey>5__3);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					<>2__current = new ConfigDefinition(<localizedSection>5__5, <canonicalKey>5__2);
					<>1__state = 3;
					return true;
				case 3:
					<>1__state = -1;
					<>2__current = new ConfigDefinition(<localizedSection>5__5, <localizedKey>5__3);
					<>1__state = 4;
					return true;
				case 4:
					<>1__state = -1;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<ConfigDefinition> IEnumerable<ConfigDefinition>.GetEnumerator()
			{
				<GetAliasDefinitions>d__161 <GetAliasDefinitions>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<GetAliasDefinitions>d__ = this;
				}
				else
				{
					<GetAliasDefinitions>d__ = new <GetAliasDefinitions>d__161(0);
				}
				<GetAliasDefinitions>d__.configKey = <>3__configKey;
				return <GetAliasDefinitions>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<ConfigDefinition>)this).GetEnumerator();
			}
		}

		private const float LiveConfigRefreshInterval = 0.03f;

		private const int SimplifiedChineseLanguageIndex = 9;

		private const string ModConfigPluginGuid = "com.github.PEAKModding.PEAKLib.ModConfig";

		private const float ModConfigUiLocalizationIntervalSeconds = 0.25f;

		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 LocalizedConfigSection = "主要";

		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 ExpressionConfigKey = "Face Expression";

		private const string LocalizedExpressionConfigKey = "表情";

		private const string DefaultExpressionName = "None";

		private const float DefaultExpressionWeight = 1f;

		private const float RuntimeScaleAdjustment = 0.78f;

		private const float BaseScaleMultiplier = 1.5f;

		private const float BundledBaseScaleMin = 0.04f;

		private const float BundledBaseScaleMax = 1.2f;

		private const FaceExpressionOption DefaultExpressionOption = FaceExpressionOption.None;

		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<FaceExpressionOption> _expressionOption;

		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 bool _lastDetectedChineseLanguage;

		private bool _isRefreshingLanguage;

		private bool _pendingConfigFileLocalizationRefresh;

		private bool _pendingConfigFileLocalizationSave;

		private float _nextModConfigUiLocalizationTime;

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

		private static readonly BindingFlags StaticFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly PropertyInfo ConfigFileEntriesProperty = typeof(ConfigFile).GetProperty("Entries", InstanceFlags);

		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.3";

		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 = ((_expressionOption == null) ? "None" : GetExpressionName(_expressionOption.Value));
				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;
			_lastDetectedChineseLanguage = DetectChineseLanguage();
			MigrateLegacyConfigIfNeeded();
			InitializeConfig(_lastDetectedChineseLanguage);
			NormalizeMigratedScaleConfigIfNeeded();
			MarkConfigFileLocalizationDirty(saveConfigFile: true);
			LoadAssets();
			try
			{
				Harmony.PatchAll(Assembly.GetExecutingAssembly());
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to apply Harmony patches: " + ex));
			}
			BindLiveConfigEvents();
			CaptureLiveConfigState();
			Log.LogInfo((object)("[ScallionMiku] Config language: " + BuildLanguageDetectionSummary(_lastDetectedChineseLanguage)));
		}

		private void Update()
		{
			HandleLanguageChangeIfNeeded();
			HandlePendingConfigFileLocalizationRefresh();
			TryLocalizeVisibleModConfigUiThrottled();
			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<FaceExpressionOption>(_expressionOption);
				_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)
		{
			MarkConfigFileLocalizationDirty(saveConfigFile: false);
			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(bool isChineseLanguage)
		{
			RemoveConfigVersionSettingIfNeeded();
			NormalizeLegacyExpressionConfigIfNeeded();
			_modEnabled = BindEntry(ConfigKey.ModEnabled, defaultValue: true, isChineseLanguage);
			_worldScaleMultiplier = BindEntry(ConfigKey.WorldScale, 0.9f, isChineseLanguage);
			_backpackScaleMultiplier = BindEntry(ConfigKey.BackpackScale, 0.4f, isChineseLanguage);
			_positionOffsetX = BindEntry(ConfigKey.PositionOffsetX, DefaultPositionOffset.x, isChineseLanguage);
			_positionOffsetY = BindEntry(ConfigKey.PositionOffsetY, DefaultPositionOffset.y, isChineseLanguage);
			_positionOffsetZ = BindEntry(ConfigKey.PositionOffsetZ, DefaultPositionOffset.z, isChineseLanguage);
			_expressionOption = BindEntry(ConfigKey.FaceExpression, FaceExpressionOption.None, isChineseLanguage);
			MigrateLocalizedConfigEntries();
		}

		private ConfigEntry<T> BindEntry<T>(ConfigKey configKey, T defaultValue, bool isChineseLanguage)
		{
			return ((BaseUnityPlugin)this).Config.Bind<T>(GetSectionName(configKey, isChineseLanguage), GetKeyName(configKey, isChineseLanguage), defaultValue, CreateConfigDescription(configKey, isChineseLanguage));
		}

		private ConfigDescription CreateConfigDescription(ConfigKey configKey, bool isChineseLanguage)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage);
			switch (configKey)
			{
			case ConfigKey.WorldScale:
				return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 1.1f), Array.Empty<object>());
			case ConfigKey.BackpackScale:
				return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>());
			case ConfigKey.PositionOffsetX:
			case ConfigKey.PositionOffsetY:
			case ConfigKey.PositionOffsetZ:
				return new ConfigDescription(localizedDescription, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>());
			default:
				return new ConfigDescription(localizedDescription, (AcceptableValueBase)null, Array.Empty<object>());
			}
		}

		private void RemoveConfigVersionSettingIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (string.IsNullOrEmpty(configFilePath) || !File.Exists(configFilePath))
				{
					return;
				}
				string[] array = File.ReadAllLines(configFilePath);
				List<string> list = new List<string>(array.Length);
				bool flag = false;
				bool flag2 = false;
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i] ?? string.Empty;
					string text2 = text.Trim();
					if (text2.StartsWith("[", StringComparison.Ordinal) && text2.EndsWith("]", StringComparison.Ordinal))
					{
						flag2 = string.Equals(text2.Substring(1, text2.Length - 2).Trim(), "Internal", StringComparison.OrdinalIgnoreCase);
						if (flag2)
						{
							flag = true;
							continue;
						}
					}
					if (flag2)
					{
						flag = true;
					}
					else
					{
						list.Add(text);
					}
				}
				if (flag)
				{
					File.WriteAllLines(configFilePath, list.ToArray());
					((BaseUnityPlugin)this).Config.Reload();
					VerboseLog("Removed obsolete Internal/Config Version config entry.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to remove obsolete Config Version entry: " + ex.Message));
			}
		}

		private void NormalizeLegacyExpressionConfigIfNeeded()
		{
			try
			{
				string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
				if (string.IsNullOrEmpty(configFilePath) || !File.Exists(configFilePath))
				{
					return;
				}
				string[] array = File.ReadAllLines(configFilePath);
				bool flag = false;
				for (int i = 0; i < array.Length; i++)
				{
					if (TrySplitConfigSettingLine(array[i], out var leading, out var keyName, out var separatorAndValue) && IsConfigKeyName(keyName, ConfigKey.FaceExpression))
					{
						int num = separatorAndValue.IndexOf('=');
						string obj = ((num >= 0) ? separatorAndValue.Substring(num + 1).Trim() : string.Empty);
						if (!TryParseExpressionOption(obj, out var option))
						{
							option = FaceExpressionOption.None;
						}
						string text = option.ToString();
						if (!string.Equals(obj, text, StringComparison.Ordinal))
						{
							string keyName2 = GetKeyName(ConfigKey.FaceExpression, _lastDetectedChineseLanguage);
							array[i] = leading + keyName2 + " = " + text;
							flag = true;
						}
					}
				}
				if (flag)
				{
					File.WriteAllLines(configFilePath, array);
					((BaseUnityPlugin)this).Config.Reload();
					VerboseLog("Migrated Face Expression config from PMX morph text to enum value for PEAKLib.ModConfig compatibility.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to normalize Face Expression config value: " + ex.Message));
			}
		}

		private static bool TryParseExpressionOption(string rawValue, out FaceExpressionOption option)
		{
			option = FaceExpressionOption.None;
			if (string.IsNullOrEmpty(rawValue))
			{
				return false;
			}
			string text = rawValue.Trim().Trim(new char[1] { '"' });
			if (Enum.TryParse<FaceExpressionOption>(text, ignoreCase: true, out option) && Enum.IsDefined(typeof(FaceExpressionOption), option))
			{
				return true;
			}
			for (int i = 0; i <= 15; i++)
			{
				FaceExpressionOption faceExpressionOption = (FaceExpressionOption)i;
				if (string.Equals(text, GetExpressionName(faceExpressionOption), StringComparison.Ordinal))
				{
					option = faceExpressionOption;
					return true;
				}
			}
			return false;
		}

		private static string GetExpressionName(FaceExpressionOption option)
		{
			return option switch
			{
				FaceExpressionOption.Smile => "笑い", 
				FaceExpressionOption.Blink => "まばたき", 
				FaceExpressionOption.Wink => "ウィンク", 
				FaceExpressionOption.WinkRight => "ウィンク右", 
				FaceExpressionOption.Wink2 => "ウィンク2", 
				FaceExpressionOption.Wink2Right => "ウィンク2右", 
				FaceExpressionOption.A => "あ", 
				FaceExpressionOption.I => "い", 
				FaceExpressionOption.U => "う", 
				FaceExpressionOption.E => "え", 
				FaceExpressionOption.O => "お", 
				FaceExpressionOption.A2 => "あ2", 
				FaceExpressionOption.MouthCornerUp => "口角上げ", 
				FaceExpressionOption.MouthCornerDown => "口角下げ", 
				FaceExpressionOption.Hau => "はぅ", 
				_ => "None", 
			};
		}

		private void MarkConfigFileLocalizationDirty(bool saveConfigFile)
		{
			_pendingConfigFileLocalizationRefresh = true;
			_pendingConfigFileLocalizationSave |= saveConfigFile;
		}

		private void HandlePendingConfigFileLocalizationRefresh()
		{
			if (_pendingConfigFileLocalizationRefresh && !_isRefreshingLanguage)
			{
				bool pendingConfigFileLocalizationSave = _pendingConfigFileLocalizationSave;
				_pendingConfigFileLocalizationRefresh = false;
				_pendingConfigFileLocalizationSave = false;
				TryRefreshLocalizedConfigFile(_lastDetectedChineseLanguage, pendingConfigFileLocalizationSave);
			}
		}

		private void HandleLanguageChangeIfNeeded()
		{
			bool flag = DetectChineseLanguage();
			if (flag != _lastDetectedChineseLanguage)
			{
				ReinitializeLocalizedConfig(flag);
			}
		}

		private void ReinitializeLocalizedConfig(bool isChineseLanguage)
		{
			if (_isRefreshingLanguage)
			{
				return;
			}
			_isRefreshingLanguage = true;
			try
			{
				_lastDetectedChineseLanguage = isChineseLanguage;
				ApplyLocalizedConfigMetadata(isChineseLanguage);
				MarkConfigFileLocalizationDirty(saveConfigFile: true);
				Log.LogInfo((object)("[ScallionMiku] Config language changed: " + (isChineseLanguage ? "Chinese" : "English")));
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[ScallionMiku] Failed to update config language: " + ex.Message));
			}
			finally
			{
				_isRefreshingLanguage = false;
			}
		}

		private void ApplyLocalizedConfigMetadata(bool isChineseLanguage)
		{
			try
			{
				ConfigEntryBase[] configEntriesSnapshot = GetConfigEntriesSnapshot(((BaseUnityPlugin)this).Config);
				foreach (ConfigEntryBase val in configEntriesSnapshot)
				{
					if (val != null && !(val.Definition == (ConfigDefinition)null) && val.Description != null && TryGetConfigKey(val.Definition.Key, out var configKey))
					{
						string localizedDescription = GetLocalizedDescription(configKey, isChineseLanguage);
						if (!string.IsNullOrWhiteSpace(localizedDescription))
						{
							SetPrivateField(val.Description, "<Description>k__BackingField", localizedDescription);
						}
					}
				}
				TryLocalizeVisibleModConfigUi();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[ScallionMiku] Failed to apply localized config metadata: " + ex.Message));
			}
		}

		private static ConfigEntryBase[] GetConfigEntriesSnapshot(ConfigFile configFile)
		{
			if (configFile == null || !(ConfigFileEntriesProperty != null) || !(ConfigFileEntriesProperty.GetValue(configFile) is IDictionary dictionary) || dictionary.Count == 0)
			{
				return Array.Empty<ConfigEntryBase>();
			}
			List<ConfigEntryBase> list = new List<ConfigEntryBase>();
			foreach (DictionaryEntry item in dictionary)
			{
				object? value = item.Value;
				ConfigEntryBase val = (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
				if (val != null)
				{
					list.Add(val);
				}
			}
			return list.ToArray();
		}

		private static void SetPrivateField(object target, string fieldName, object value)
		{
			if (target != null && !string.IsNullOrWhiteSpace(fieldName))
			{
				target.GetType().GetField(fieldName, InstanceFlags)?.SetValue(target, value);
			}
		}

		private void TryRefreshLocalizedConfigFile(bool isChineseLanguage, bool saveConfigFile)
		{
			try
			{
				if (((BaseUnityPlugin)this).Config != null && !string.IsNullOrWhiteSpace(((BaseUnityPlugin)this).Config.ConfigFilePath))
				{
					if (saveConfigFile)
					{
						((BaseUnityPlugin)this).Config.Save();
					}
					RewriteConfigFileLocalization(((BaseUnityPlugin)this).Config.ConfigFilePath, isChineseLanguage);
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[ScallionMiku] Failed to refresh localized config file: " + ex.Message));
			}
		}

		private static void RewriteConfigFileLocalization(string configFilePath, bool isChineseLanguage)
		{
			if (!string.IsNullOrWhiteSpace(configFilePath) && File.Exists(configFilePath))
			{
				string[] array = File.ReadAllLines(configFilePath);
				string[] array2 = new string[array.Length];
				bool flag = false;
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i] ?? string.Empty;
					flag |= !string.Equals(text, array2[i] = RewriteConfigFileLine(text, isChineseLanguage), StringComparison.Ordinal);
				}
				if (flag)
				{
					File.WriteAllLines(configFilePath, array2);
				}
			}
		}

		private static string RewriteConfigFileLine(string line, bool isChineseLanguage)
		{
			if (string.IsNullOrWhiteSpace(line))
			{
				return line ?? string.Empty;
			}
			string text = line.Trim();
			if (text.StartsWith("[", StringComparison.Ordinal) && text.EndsWith("]", StringComparison.Ordinal))
			{
				if (!TryGetLocalizedSectionName(text.Substring(1, text.Length - 2).Trim(), isChineseLanguage, out var localizedSectionName))
				{
					return line;
				}
				int num = line.IndexOf('[');
				int num2 = line.LastIndexOf(']');
				if (num < 0 || num2 < num)
				{
					return line;
				}
				return line.Substring(0, num + 1) + localizedSectionName + line.Substring(num2);
			}
			if (!TrySplitConfigSettingLine(line, out var leading, out var keyName, out var separatorAndValue))
			{
				return line;
			}
			if (!TryGetConfigKey(keyName, out var configKey))
			{
				return line;
			}
			return leading + GetKeyName(configKey, isChineseLanguage) + separatorAndValue;
		}

		private static bool TrySplitConfigSettingLine(string line, out string leading, out string keyName, out string separatorAndValue)
		{
			leading = string.Empty;
			keyName = string.Empty;
			separatorAndValue = string.Empty;
			if (string.IsNullOrWhiteSpace(line))
			{
				return false;
			}
			string text = line.TrimStart(Array.Empty<char>());
			if (text.StartsWith("#", StringComparison.Ordinal) || text.StartsWith(";", StringComparison.Ordinal))
			{
				return false;
			}
			int num = line.IndexOf('=');
			if (num <= 0)
			{
				return false;
			}
			int i;
			for (i = 0; i < num && char.IsWhiteSpace(line[i]); i++)
			{
			}
			int num2 = num - 1;
			while (num2 >= i && char.IsWhiteSpace(line[num2]))
			{
				num2--;
			}
			if (num2 < i)
			{
				return false;
			}
			leading = line.Substring(0, i);
			keyName = line.Substring(i, num2 - i + 1);
			separatorAndValue = line.Substring(num2 + 1);
			return true;
		}

		private static bool TryGetLocalizedSectionName(string sectionName, bool isChineseLanguage, out string localizedSectionName)
		{
			if (string.Equals(sectionName, "Main", StringComparison.OrdinalIgnoreCase) || string.Equals(sectionName, "主要", StringComparison.Ordinal))
			{
				localizedSectionName = (isChineseLanguage ? "主要" : "Main");
				return true;
			}
			localizedSectionName = string.Empty;
			return false;
		}

		private void MigrateLocalizedConfigEntries()
		{
			IDictionary orphanedEntries = GetOrphanedEntries(((BaseUnityPlugin)this).Config);
			if (orphanedEntries != null && orphanedEntries.Count != 0 && (false | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_modEnabled, ConfigKey.ModEnabled, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_worldScaleMultiplier, ConfigKey.WorldScale, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_backpackScaleMultiplier, ConfigKey.BackpackScale, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetX, ConfigKey.PositionOffsetX, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetY, ConfigKey.PositionOffsetY, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_positionOffsetZ, ConfigKey.PositionOffsetZ, orphanedEntries) | TryMigrateLocalizedConfigValue((ConfigEntryBase)(object)_expressionOption, ConfigKey.FaceExpression, orphanedEntries)))
			{
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		private static bool TryMigrateLocalizedConfigValue(ConfigEntryBase entry, ConfigKey configKey, IDictionary orphanedEntries)
		{
			if (entry == null || entry.Definition == (ConfigDefinition)null || orphanedEntries == null)
			{
				return false;
			}
			bool flag = false;
			foreach (ConfigDefinition aliasDefinition in GetAliasDefinitions(configKey))
			{
				if (DefinitionsEqual(aliasDefinition, entry.Definition) || !orphanedEntries.Contains(aliasDefinition))
				{
					continue;
				}
				if (!flag)
				{
					object obj = orphanedEntries[aliasDefinition];
					if (obj != null)
					{
						entry.SetSerializedValue(NormalizeSerializedConfigValue(configKey, obj.ToString()));
					}
					flag = true;
				}
				orphanedEntries.Remove(aliasDefinition);
			}
			return flag;
		}

		private static string NormalizeSerializedConfigValue(ConfigKey configKey, string serializedValue)
		{
			if (configKey == ConfigKey.FaceExpression && TryParseExpressionOption(serializedValue, out var option))
			{
				return option.ToString();
			}
			return serializedValue;
		}

		[IteratorStateMachine(typeof(<GetAliasDefinitions>d__161))]
		private static IEnumerable<ConfigDefinition> GetAliasDefinitions(ConfigKey configKey)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <GetAliasDefinitions>d__161(-2)
			{
				<>3__configKey = configKey
			};
		}

		private static IDictionary GetOrphanedEntries(ConfigFile configFile)
		{
			return ((object)configFile)?.GetType().GetProperty("OrphanedEntries", InstanceFlags)?.GetValue(configFile) as IDictionary;
		}

		private static bool DefinitionsEqual(ConfigDefinition left, ConfigDefinition right)
		{
			if (string.Equals((left != null) ? left.Section : null, (right != null) ? right.Section : null, StringComparison.Ordinal))
			{
				return string.Equals((left != null) ? left.Key : null, (right != null) ? right.Key : null, StringComparison.Ordinal);
			}
			return false;
		}

		private static bool DetectChineseLanguage()
		{
			bool isChineseLanguage;
			bool num = TryGetConfiguredGameLanguage(out isChineseLanguage);
			string languageName;
			bool flag = TryGetLocalizedTextLanguageName(out languageName);
			if (num && isChineseLanguage)
			{
				return true;
			}
			if (flag && IsChineseLanguageName(languageName))
			{
				return true;
			}
			return false;
		}

		private static string BuildLanguageDetectionSummary(bool isChineseLanguage)
		{
			bool isChineseLanguage2;
			string languageValueText;
			string text = (TryGetConfiguredGameLanguage(out isChineseLanguage2, out languageValueText) ? (languageValueText + "/" + (isChineseLanguage2 ? "Chinese" : "English")) : "unknown");
			string languageName;
			string text2 = (TryGetLocalizedTextLanguageName(out languageName) ? languageName : "unknown");
			return (isChineseLanguage ? "Chinese" : "English") + " (prefs=" + text + ", runtime=" + text2 + ")";
		}

		private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage)
		{
			string languageValueText;
			return TryGetConfiguredGameLanguage(out isChineseLanguage, out languageValueText);
		}

		private static bool TryGetConfiguredGameLanguage(out bool isChineseLanguage, out string languageValueText)
		{
			isChineseLanguage = false;
			languageValueText = string.Empty;
			try
			{
				if (!PlayerPrefs.HasKey("LanguageSetting"))
				{
					return false;
				}
				int result = PlayerPrefs.GetInt("LanguageSetting", int.MinValue);
				if (result != int.MinValue)
				{
					languageValueText = result.ToString(CultureInfo.InvariantCulture);
					isChineseLanguage = IsChineseLanguageIndex(result);
					return true;
				}
				string text = (languageValueText = PlayerPrefs.GetString("LanguageSetting", string.Empty));
				if (string.IsNullOrWhiteSpace(text))
				{
					return false;
				}
				if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result))
				{
					isChineseLanguage = IsChineseLanguageIndex(result);
					return true;
				}
				isChineseLanguage = IsChineseLanguageName(text);
				return true;
			}
			catch
			{
				return false;
			}
		}

		private static bool TryGetLocalizedTextLanguageName(out string languageName)
		{
			languageName = string.Empty;
			try
			{
				languageName = ((object)(Language)(ref LocalizedText.CURRENT_LANGUAGE)).ToString();
				return !string.IsNullOrWhiteSpace(languageName);
			}
			catch
			{
				return false;
			}
		}

		private static bool IsChineseLanguageName(string languageName)
		{
			if (string.IsNullOrWhiteSpace(languageName))
			{
				return false;
			}
			if (int.TryParse(languageName.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
			{
				return IsChineseLanguageIndex(result);
			}
			if (languageName.IndexOf("Chinese", StringComparison.OrdinalIgnoreCase) < 0 && languageName.IndexOf("中文", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return languageName.StartsWith("zh", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private static bool IsChineseLanguageIndex(int languageValue)
		{
			if (languageValue != 9)
			{
				return languageValue == 10;
			}
			return true;
		}

		private static string GetConfigSectionName(ConfigKey configKey)
		{
			return GetSectionName(configKey, isChineseLanguage: false);
		}

		private static string GetSectionName(ConfigKey configKey, bool isChineseLanguage)
		{
			if (!isChineseLanguage)
			{
				return "Main";
			}
			return "主要";
		}

		private static string GetConfigKeyName(ConfigKey configKey)
		{
			return GetKeyName(configKey, isChineseLanguage: false);
		}

		private static string GetKeyName(ConfigKey configKey, bool isChineseLanguage)
		{
			if (isChineseLanguage)
			{
				switch (configKey)
				{
				case ConfigKey.ModEnabled:
					return "启用葱音未来替换";
				case ConfigKey.WorldScale:
					return "世界模型大小";
				case ConfigKey.BackpackScale:
					return "背包模型大小";
				case ConfigKey.PositionOffsetX:
					return "模型位置偏移 X";
				case ConfigKey.PositionOffsetY:
					return "模型位置偏移 Y";
				case ConfigKey.PositionOffsetZ:
					return "模型位置偏移 Z";
				case ConfigKey.FaceExpression:
					return "表情";
				}
			}
			return configKey switch
			{
				ConfigKey.ModEnabled => "Enable Fufu Replacement", 
				ConfigKey.WorldScale => "Fufu Size In World", 
				ConfigKey.BackpackScale => "Backpack Model Scale", 
				ConfigKey.PositionOffsetX => "Model Position Offset X", 
				ConfigKey.PositionOffsetY => "Model Position Offset Y", 
				ConfigKey.PositionOffsetZ => "Model Position Offset Z", 
				ConfigKey.FaceExpression => "Face Expression", 
				_ => string.Empty, 
			};
		}

		private static string GetLocalizedDescription(ConfigKey configKey, bool isChineseLanguage)
		{
			if (isChineseLanguage)
			{
				switch (configKey)
				{
				case ConfigKey.ModEnabled:
					return "总开关。关闭后会恢复原版 BingBong 的外观、名称、图标和碰撞体。";
				case ConfigKey.WorldScale:
					return "葱音未来模型在手持或放在世界中时的大小倍率。";
				case ConfigKey.BackpackScale:
					return "葱音未来模型显示在背包中时的大小倍率。";
				case ConfigKey.PositionOffsetX:
					return "运行时模型在 X 轴上的额外本地位置偏移。";
				case ConfigKey.PositionOffsetY:
					return "运行时模型在 Y 轴上的额外本地位置偏移。";
				case ConfigKey.PositionOffsetZ:
					return "运行时模型在 Z 轴上的额外本地位置偏移。";
				case ConfigKey.FaceExpression:
					return "基础 PMX 表情。枚举会在运行时映射回实际 morph 名称,例如 Smile=笑い,Blink=まばたき,Wink=ウィンク。";
				}
			}
			return configKey switch
			{
				ConfigKey.ModEnabled => "Master switch for the mod. When disabled, the original BingBong visuals, name, icon, and colliders are restored.", 
				ConfigKey.WorldScale => "Scale multiplier for Fufu while held or lying in the world.", 
				ConfigKey.BackpackScale => "Scale multiplier for the replacement model while the item is shown in the backpack.", 
				ConfigKey.PositionOffsetX => "Extra local position offset on the X axis for the runtime model.", 
				ConfigKey.PositionOffsetY => "Extra local position offset on the Y axis for the runtime model.", 
				ConfigKey.PositionOffsetZ => "Extra local position offset on the Z axis for the runtime model.", 
				ConfigKey.FaceExpression => "Base PMX facial expression. Mapping: Smile=笑い, Blink=まばたき, Wink=ウィンク, WinkRight=ウィンク右, Wink2=ウィンク2, Wink2Right=ウィンク2右, A=あ, I=い, U=う, E=え, O=お, A2=あ2, MouthCornerUp=口角上げ, MouthCornerDown=口角下げ, Hau=はぅ.", 
				_ => string.Empty, 
			};
		}

		private static bool TryGetConfigKey(string keyName, out ConfigKey configKey)
		{
			foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey)))
			{
				if (IsConfigKeyName(keyName, value))
				{
					configKey = value;
					return true;
				}
			}
			configKey = ConfigKey.ModEnabled;
			return false;
		}

		private static bool IsConfigKeyName(string keyName, ConfigKey configKey)
		{
			if (!string.Equals(keyName, GetConfigKeyName(configKey), StringComparison.OrdinalIgnoreCase))
			{
				return string.Equals(keyName, GetKeyName(configKey, isChineseLanguage: true), StringComparison.Ordinal);
			}
			return true;
		}

		private void TryLocalizeVisibleModConfigUiThrottled()
		{
			if (!(Time.unscaledTime < _nextModConfigUiLocalizationTime))
			{
				_nextModConfigUiLocalizationTime = Time.unscaledTime + 0.25f;
				TryLocalizeVisibleModConfigUi();
			}
		}

		private void TryLocalizeVisibleModConfigUi()
		{
			if (!TryGetModConfigMenuInstance(out var menuType, out var menuInstance))
			{
				return;
			}
			Behaviour val = (Behaviour)((menuInstance is Behaviour) ? menuInstance : null);
			if (val == null || (Object)(object)val == (Object)null)
			{
				return;
			}
			try
			{
				if (!val.isActiveAndEnabled || !((Component)val).gameObject.activeInHierarchy)
				{
					return;
				}
			}
			catch
			{
				return;
			}
			Dictionary<string, string> map = BuildModConfigUiLocalizationMap(DetectChineseLanguage());
			foreach (Transform item in EnumerateModConfigUiRoots(menuInstance, menuType))
			{
				ApplyTextLocalizationToRoot(item, map);
			}
			ApplyTextLocalizationToLoadedUi(map);
		}

		private static bool TryGetModConfigMenuInstance(out Type menuType, out object menuInstance)
		{
			menuType = null;
			menuInstance = null;
			if (!Chainloader.PluginInfos.TryGetValue("com.github.PEAKModding.PEAKLib.ModConfig", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				return false;
			}
			Assembly assembly = ((object)value.Instance).GetType().Assembly;
			menuType = assembly.GetType("PEAKLib.ModConfig.Components.ModdedSettingsMenu");
			menuInstance = menuType?.GetProperty("Instance", StaticFlags)?.GetValue(null);
			if (menuType != null)
			{
				return menuInstance != null;
			}
			return false;
		}

		[IteratorStateMachine(typeof(<EnumerateModConfigUiRoots>d__181))]
		private static IEnumerable<Transform> EnumerateModConfigUiRoots(object menuInstance, Type menuType)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateModConfigUiRoots>d__181(-2)
			{
				<>3__menuInstance = menuInstance,
				<>3__menuType = menuType
			};
		}

		[IteratorStateMachine(typeof(<EnumerateCandidateTransforms>d__182))]
		private static IEnumerable<Transform> EnumerateCandidateTransforms(object menuInstance, Type menuType)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnumerateCandidateTransforms>d__182(-2)
			{
				<>3__menuInstance = menuInstance,
				<>3__menuType = menuType
			};
		}

		private static void ApplyTextLocalizationToRoot(Transform root, Dictionary<string, string> map)
		{
			if (!((Object)(object)root == (Object)null) && map != null && map.Count != 0)
			{
				TMP_Text[] componentsInChildren = ((Component)root).GetComponentsInChildren<TMP_Text>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					ApplyTextLocalization(componentsInChildren[i], map);
				}
			}
		}

		private static void ApplyTextLocalizationToLoadedUi(Dictionary<string, string> map)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (map == null || map.Count == 0)
			{
				return;
			}
			try
			{
				TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
				foreach (TMP_Text val in array)
				{
					if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null))
					{
						Scene scene = ((Component)val).gameObject.scene;
						if (((Scene)(ref scene)).IsValid())
						{
							ApplyTextLocalization(val, map);
						}
					}
				}
			}
			catch
			{
			}
		}

		private static void ApplyTextLocalization(TMP_Text text, Dictionary<string, string> map)
		{
			if (!((Object)(object)text == (Object)null) && map != null && map.Count != 0)
			{
				string text2 = ((text.text == null) ? string.Empty : text.text.Trim());
				if (!string.IsNullOrWhiteSpace(text2) && map.TryGetValue(text2, out var value) && !string.Equals(text2, value, StringComparison.Ordinal))
				{
					text.text = value;
				}
			}
		}

		private static Dictionary<string, string> BuildModConfigUiLocalizationMap(bool isChineseLanguage)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			AddUiLocalizationPair(dictionary, "ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage));
			AddUiLocalizationPair(dictionary, "ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage));
			AddUiLocalizationPair(dictionary, "com.github.Thanks.ScallionMiku", GetLocalizedModDisplayName(isChineseLanguage));
			AddUiLocalizationPair(dictionary, "Main", GetSectionName(ConfigKey.ModEnabled, isChineseLanguage));
			AddUiLocalizationPair(dictionary, "主要", GetSectionName(ConfigKey.ModEnabled, isChineseLanguage));
			foreach (ConfigKey value in Enum.GetValues(typeof(ConfigKey)))
			{
				string sectionName = GetSectionName(value, isChineseLanguage);
				string keyName = GetKeyName(value, isChineseLanguage);
				AddUiLocalizationPair(dictionary, GetConfigSectionName(value), sectionName);
				AddUiLocalizationPair(dictionary, GetSectionName(value, isChineseLanguage: true), sectionName);
				AddUiLocalizationPair(dictionary, GetConfigKeyName(value), keyName);
				AddUiLocalizationPair(dictionary, ToReadableName(GetConfigKeyName(value)), keyName);
				AddUiLocalizationPair(dictionary, GetKeyName(value, isChineseLanguage: true), keyName);
				AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: false), GetLocalizedDescription(value, isChineseLanguage));
				AddUiLocalizationPair(dictionary, GetLocalizedDescription(value, isChineseLanguage: true), GetLocalizedDescription(value, isChineseLanguage));
			}
			AddExpressionOptionUiLocalization(dictionary, isChineseLanguage);
			return dictionary;
		}

		private static void AddExpressionOptionUiLocalization(Dictionary<string, string> map, bool isChineseLanguage)
		{
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.None, isChineseLanguage, "无");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Smile, isChineseLanguage, "笑い");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Blink, isChineseLanguage, "眨眼");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink, isChineseLanguage, "眨左眼");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.WinkRight, isChineseLanguage, "眨右眼");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink2, isChineseLanguage, "眨左眼 2");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Wink2Right, isChineseLanguage, "眨右眼 2");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.A, isChineseLanguage, "口型 あ");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.I, isChineseLanguage, "口型 い");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.U, isChineseLanguage, "口型 う");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.E, isChineseLanguage, "口型 え");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.O, isChineseLanguage, "口型 お");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.A2, isChineseLanguage, "口型 あ2");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.MouthCornerUp, isChineseLanguage, "嘴角上扬");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.MouthCornerDown, isChineseLanguage, "嘴角下垂");
			AddExpressionOptionUiLocalizationPair(map, FaceExpressionOption.Hau, isChineseLanguage, "はぅ");
		}

		private static void AddExpressionOptionUiLocalizationPair(Dictionary<string, string> map, FaceExpressionOption option, bool isChineseLanguage, string chineseLabel)
		{
			string text = option.ToString();
			if (isChineseLanguage)
			{
				AddUiLocalizationPair(map, text, chineseLabel);
			}
			else
			{
				AddUiLocalizationPair(map, chineseLabel, text);
			}
		}

		private static void AddUiLocalizationPair(Dictionary<string, string> map, string source, string localized)
		{
			if (map != null && !string.IsNullOrWhiteSpace(source) && !string.IsNullOrWhiteSpace(localized))
			{
				string text = source.Trim();
				string text3 = (map[text] = localized.Trim());
				map[text3] = text3;
				string key = text.Replace(" ", string.Empty);
				string key2 = text3.Replace(" ", string.Empty);
				if (!map.ContainsKey(key))
				{
					map[key] = text3;
				}
				if (!map.ContainsKey(key2))
				{
					map[key2] = text3;
				}
				map[text.ToUpperInvariant()] = text3;
				map[text3.ToUpperInvariant()] = text3;
			}
		}

		private static string ToReadableName(string keyName)
		{
			if (string.IsNullOrWhiteSpace(keyName))
			{
				return string.Empty;
			}
			List<char> list = new List<char>(keyName.Length + 8);
			for (int i = 0; i < keyName.Length; i++)
			{
				char c = keyName[i];
				if (i > 0 && char.IsUpper(c) && !char.IsWhiteSpace(keyName[i - 1]) && !char.IsUpper(keyName[i - 1]))
				{
					list.Add(' ');
				}
				list.Add(c);
			}
			return new string(list.ToArray());
		}

		private static string GetLocalizedModDisplayName(bool isChineseLanguage)
		{
			if (!isChineseLanguage)
			{
				return "ScallionMiku";
			}
			return "葱音未来";
		}

		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 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)n