Decompiled source of ScallionMiku v1.0.1
plugins/ScallionMiku.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("ScallionMiku")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: AssemblyInformationalVersion("0.4.0")] [assembly: AssemblyProduct("ScallionMiku")] [assembly: AssemblyTitle("ScallionMiku")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.0.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class IgnoresAccessChecksToAttribute : Attribute { private readonly string _assemblyName; public string AssemblyName => _assemblyName; public IgnoresAccessChecksToAttribute(string assemblyName) { _assemblyName = assemblyName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] public sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte value) { NullableFlags = new byte[1] { value }; } public NullableAttribute(byte[] value) { NullableFlags = value; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] public sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte value) { Flag = value; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int version) { Version = version; } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class BepInAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public BepInAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class PatcherAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public PatcherAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace ScallionMiku { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.Thanks.ScallionMiku", "ScallionMiku", "1.0.0")] public class Plugin : BaseUnityPlugin { private const float LiveConfigRefreshInterval = 0.03f; private static readonly string[] LegacyPluginIds = new string[2] { "com.github.Thanks.MikuBongFix", "com.github.FelineEntity.MikuBongFix" }; private const string BundleFileName = "ScallionMiku"; private const string ExternalIconFileName = "ScallionMikuUI.png"; private const string PrefabAssetPath = "assets/葱音未来_by_翼月生/scallionmiku.prefab"; private const string MaterialAssetPath = "assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat"; private const string IconTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png"; private const string MainTextureAssetPath = "assets/葱音未来_by_翼月生/textures/身体.png"; private const string ConfigSection = "Main"; private const string WorldScaleConfigKey = "Fufu Size In World"; private const string BackpackModelScaleConfigKey = "Backpack Model Scale"; private const string LegacyFufuBackpackScaleConfigKey = "Fufu Size In Backpack"; private const string LegacyMikuBackpackScaleConfigKey = "Miku Size In Backpack"; private const float WorldMinScaleMultiplier = 0.4f; private const float WorldMaxScaleMultiplier = 1.1f; private const float BackpackMinScaleMultiplier = 0.2f; private const float BackpackMaxScaleMultiplier = 1f; private const float PositionOffsetMin = -2f; private const float PositionOffsetMax = 2f; private const float DefaultWorldScaleMultiplier = 0.9f; private const float DefaultBackpackScaleMultiplier = 0.4f; private const string DefaultExpressionName = "None"; private const float DefaultExpressionWeight = 1f; private const float RuntimeScaleAdjustment = 0.78f; private const float BaseScaleMultiplier = 1.5f; private const int CurrentConfigVersion = 1; private const float BundledBaseScaleMin = 0.04f; private const float BundledBaseScaleMax = 1.2f; private static readonly string[] ExpressionOptions = new string[16] { "None", "笑い", "まばたき", "ウィンク", "ウィンク右", "ウィンク2", "ウィンク2右", "あ", "い", "う", "え", "お", "あ2", "口角上げ", "口角下げ", "はぅ" }; private static readonly Vector3 DefaultBundledReplacementBaseScale = new Vector3(0.52f, 0.52f, 0.52f); private static readonly Vector3 RuntimeReferenceVisibleSizeAtBaseScale = new Vector3(1.5852638f, 1.2168914f, 0.8999324f); private static readonly Vector3 DefaultPositionOffset = Vector3.zero; private static readonly string[] PreferredTextureProps = new string[2] { "_BaseMap", "_MainTex" }; private static readonly string[] PrefabNameHints = new string[3] { "scallionmiku", "miku", "scallion" }; private static readonly string[] MaterialNameHints = new string[3] { "scallionmiku-8.shintai", "shintai", "miku" }; private static readonly string[] IconTextureNameHints = new string[4] { "身体", "shintai", "miku", "scallionmiku" }; private static readonly string[] MainTextureNameHints = new string[5] { "身体", "shintai", "miku", "scallionmiku", "albedo" }; private static readonly Color MikuStyleTint = new Color(0.98f, 1f, 1f, 1f); private static ConfigEntry<bool> _modEnabled; private static ConfigEntry<float> _worldScaleMultiplier; private static ConfigEntry<float> _backpackScaleMultiplier; private static ConfigEntry<float> _positionOffsetX; private static ConfigEntry<float> _positionOffsetY; private static ConfigEntry<float> _positionOffsetZ; private static ConfigEntry<string> _expressionName; private static ConfigEntry<int> _configVersion; private bool _liveConfigStateInitialized; private bool _lastObservedModEnabled; private float _lastObservedWorldScale; private float _lastObservedBackpackScale; private Vector3 _lastObservedPositionOffset; private string _lastObservedExpressionName; private bool _pendingLiveConfigRefresh; private float _nextLiveConfigRefreshTime; private bool _liveConfigEventsBound; private static ManualLogSource _log; private static AssetBundle _bundle; private static GameObject _mochiPrefab; private static Material _mochiMaterial; private static Material _runtimeMikuMaterial; private static Texture2D _mochiTexture; private static Texture2D _mikuMainTexture; private static Vector3 _bundledReplacementBaseScale = DefaultBundledReplacementBaseScale; private static RuntimeReplacementModel _runtimeReplacementModel; public const string Name = "ScallionMiku"; public const string Id = "com.github.Thanks.ScallionMiku"; public const string Version = "1.0.0"; internal static Harmony Harmony = new Harmony("com.github.Thanks.ScallionMiku"); internal static ManualLogSource Log { get { return _log; } private set { _log = value; } } internal static AssetBundle Bundle { get { return _bundle; } private set { _bundle = value; } } internal static GameObject MochiPrefab { get { return _mochiPrefab; } private set { _mochiPrefab = value; } } internal static Material MochiMaterial { get { return _mochiMaterial; } private set { _mochiMaterial = value; } } internal static Material RuntimeMikuMaterial { get { return _runtimeMikuMaterial; } private set { _runtimeMikuMaterial = value; } } internal static Texture2D MochiTexture { get { return _mochiTexture; } private set { _mochiTexture = value; } } internal static Texture2D MikuMainTexture { get { return _mikuMainTexture; } private set { _mikuMainTexture = value; } } internal static RuntimeReplacementModel RuntimeReplacementModel { get { return _runtimeReplacementModel; } private set { _runtimeReplacementModel = value; } } internal static bool ModEnabled { get { if (_modEnabled != null) { return _modEnabled.Value; } return true; } } internal static bool KeepOriginalRendererRefs => RuntimeReplacementModel == null; internal static bool EnableVisibilityGuard => true; internal static float WorldScaleMultiplier { get { if (_worldScaleMultiplier != null) { return Mathf.Clamp(_worldScaleMultiplier.Value, 0.4f, 1.1f); } return 0.9f; } } internal static float DefaultWorldScaleSetting => 0.9f; internal static float BackpackScaleMultiplier { get { if (_backpackScaleMultiplier != null) { return Mathf.Clamp(_backpackScaleMultiplier.Value, 0.2f, 1f); } return 0.4f; } } internal static float DefaultBackpackScaleSetting => 0.4f; internal static Vector3 ReplacementBaseScale { get { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (RuntimeReplacementModel == null) { return _bundledReplacementBaseScale * 0.78f * 1.5f; } return RuntimeReplacementModel.RecommendedBaseScale * 0.78f * 1.5f; } } internal static Vector3 PositionOffset => new Vector3((_positionOffsetX == null) ? DefaultPositionOffset.x : Mathf.Clamp(_positionOffsetX.Value, -2f, 2f), (_positionOffsetY == null) ? DefaultPositionOffset.y : Mathf.Clamp(_positionOffsetY.Value, -2f, 2f), (_positionOffsetZ == null) ? DefaultPositionOffset.z : Mathf.Clamp(_positionOffsetZ.Value, -2f, 2f)); internal static string ExpressionName { get { string text = ((_expressionName == null) ? "None" : (_expressionName.Value ?? "None").Trim()); if (!string.IsNullOrEmpty(text)) { return text; } return "None"; } } internal static float ExpressionWeight => 1f; internal static string ReplacementDisplayName => "Miku"; internal static int ReplacementRefreshRevision { get; private set; } = 1; internal static string directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; MigrateLegacyConfigIfNeeded(); InitializeConfig(); NormalizeMigratedScaleConfigIfNeeded(); NormalizePositionBaselineConfigIfNeeded(); LoadAssets(); try { Harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception ex) { Log.LogError((object)("Failed to apply Harmony patches: " + ex)); } BindLiveConfigEvents(); CaptureLiveConfigState(); } private void Update() { if (HasLiveConfigStateChanged()) { CaptureLiveConfigState(); _pendingLiveConfigRefresh = true; } if (_pendingLiveConfigRefresh && !(Time.realtimeSinceStartup < _nextLiveConfigRefreshTime)) { RefreshReplacementInstancesNow(); } } private bool HasLiveConfigStateChanged() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!_liveConfigStateInitialized) { return true; } if (_lastObservedModEnabled != ModEnabled) { return true; } if (!Mathf.Approximately(_lastObservedWorldScale, WorldScaleMultiplier)) { return true; } if (!Mathf.Approximately(_lastObservedBackpackScale, BackpackScaleMultiplier)) { return true; } if (_lastObservedPositionOffset != PositionOffset) { return true; } return !string.Equals(_lastObservedExpressionName, ExpressionName, StringComparison.Ordinal); } private void CaptureLiveConfigState() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) _lastObservedModEnabled = ModEnabled; _lastObservedWorldScale = WorldScaleMultiplier; _lastObservedBackpackScale = BackpackScaleMultiplier; _lastObservedPositionOffset = PositionOffset; _lastObservedExpressionName = ExpressionName; _liveConfigStateInitialized = true; } private void BindLiveConfigEvents() { if (!_liveConfigEventsBound) { BindLiveConfigEvent<bool>(_modEnabled); BindLiveConfigEvent<float>(_worldScaleMultiplier); BindLiveConfigEvent<float>(_backpackScaleMultiplier); BindLiveConfigEvent<float>(_positionOffsetX); BindLiveConfigEvent<float>(_positionOffsetY); BindLiveConfigEvent<float>(_positionOffsetZ); BindLiveConfigEvent<string>(_expressionName); _liveConfigEventsBound = true; } } private void BindLiveConfigEvent<T>(ConfigEntry<T> entry) { if (entry != null) { entry.SettingChanged -= OnLiveConfigSettingChanged; entry.SettingChanged += OnLiveConfigSettingChanged; } } private void OnLiveConfigSettingChanged(object sender, EventArgs args) { CaptureLiveConfigState(); if (Time.realtimeSinceStartup >= _nextLiveConfigRefreshTime) { RefreshReplacementInstancesNow(); } else { _pendingLiveConfigRefresh = true; } } private void RefreshReplacementInstancesNow() { _pendingLiveConfigRefresh = false; _nextLiveConfigRefreshTime = Time.realtimeSinceStartup + 0.03f; ReplacementRefreshRevision = ((ReplacementRefreshRevision == int.MaxValue) ? 1 : (ReplacementRefreshRevision + 1)); Patch_AskRoutine.HandleModConfigStateChanged(); ItemPatch.RefreshAllReplacementInstances(); } private void MigrateLegacyConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (string.IsNullOrEmpty(configFilePath) || File.Exists(configFilePath) || LegacyPluginIds == null) { return; } for (int i = 0; i < LegacyPluginIds.Length; i++) { string text = LegacyPluginIds[i]; if (!string.IsNullOrEmpty(text)) { string text2 = Path.Combine(Paths.ConfigPath, text + ".cfg"); if (File.Exists(text2)) { File.Copy(text2, configFilePath, overwrite: false); ((BaseUnityPlugin)this).Config.Reload(); VerboseLog("Migrated legacy config to: " + configFilePath); break; } } } } catch (Exception ex) { Log.LogWarning((object)("Failed to migrate legacy config file: " + ex.Message)); } } private void InitializeConfig() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Expected O, but got Unknown _modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Main", "Enable Fufu Replacement", true, new ConfigDescription("Master switch for the mod. When disabled, the original BingBong visuals, name, icon, and colliders are restored.", (AcceptableValueBase)null, Array.Empty<object>())); _worldScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Fufu Size In World", 0.9f, new ConfigDescription("Scale multiplier for Fufu while held or lying in the world.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.4f, 1.1f), Array.Empty<object>())); _backpackScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Backpack Model Scale", 0.4f, new ConfigDescription("Scale multiplier for the replacement model while the item is shown in the backpack.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>())); _positionOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset X", DefaultPositionOffset.x, new ConfigDescription("Extra local position offset on the X axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>())); _positionOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset Y", DefaultPositionOffset.y, new ConfigDescription("Extra local position offset on the Y axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>())); _positionOffsetZ = ((BaseUnityPlugin)this).Config.Bind<float>("Main", "Model Position Offset Z", DefaultPositionOffset.z, new ConfigDescription("Extra local position offset on the Z axis for the runtime model.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), Array.Empty<object>())); _expressionName = ((BaseUnityPlugin)this).Config.Bind<string>("Main", "Face Expression", "None", new ConfigDescription("PMX facial expression morph name. Examples: None, 笑い, まばたき, ウィンク, ウィンク右, あ, い, う, え, お", (AcceptableValueBase)(object)new AcceptableValueList<string>(ExpressionOptions), Array.Empty<object>())); _configVersion = ((BaseUnityPlugin)this).Config.Bind<int>("Internal", "Config Version", 1, new ConfigDescription("Internal migration marker for ScallionMiku.", (AcceptableValueBase)null, Array.Empty<object>())); } private void NormalizeMigratedScaleConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (!string.IsNullOrEmpty(configFilePath) && File.Exists(configFilePath) && (FileContainsSetting(configFilePath, "Miku Size In World") || FileContainsSetting(configFilePath, "Fufu Size In Backpack") || FileContainsSetting(configFilePath, "Miku Size In Backpack") || FileContainsSetting(configFilePath, "Enable Miku Replacement"))) { bool flag = false; if (TryReadFloatSetting(configFilePath, "Miku Size In World", out var value) && _worldScaleMultiplier != null && _worldScaleMultiplier.Value <= 0.4001f) { _worldScaleMultiplier.Value = Mathf.Clamp(value, 0.4f, 1.1f); flag = true; } if (!FileContainsSetting(configFilePath, "Backpack Model Scale") && TryReadFirstFloatSetting(configFilePath, out var value2, "Fufu Size In Backpack", "Miku Size In Backpack") && _backpackScaleMultiplier != null) { _backpackScaleMultiplier.Value = Mathf.Clamp(value2, 0.2f, 1f); flag = true; } if (flag) { ((BaseUnityPlugin)this).Config.Save(); VerboseLog("Normalized migrated ScallionMiku scale settings for current runtime model."); } } } catch (Exception ex) { Log.LogWarning((object)("Failed to normalize migrated config values: " + ex.Message)); } } private static bool FileContainsSetting(string configPath, string key) { if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath)) { return false; } string[] array = File.ReadAllLines(configPath); foreach (string text in array) { if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal)) { return true; } } return false; } private static bool TryReadFloatSetting(string configPath, string key, out float value) { value = 0f; if (string.IsNullOrEmpty(configPath) || string.IsNullOrEmpty(key) || !File.Exists(configPath)) { return false; } string[] array = File.ReadAllLines(configPath); foreach (string text in array) { if (text != null && text.StartsWith(key + " =", StringComparison.Ordinal)) { return float.TryParse(text.Substring((key + " =").Length).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out value); } } return false; } private static bool TryReadFirstFloatSetting(string configPath, out float value, params string[] keys) { value = 0f; if (keys == null || keys.Length == 0) { return false; } foreach (string key in keys) { if (TryReadFloatSetting(configPath, key, out value)) { return true; } } return false; } private void NormalizePositionBaselineConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; if (!string.IsNullOrEmpty(configFilePath) && File.Exists(configFilePath) && (!FileContainsSetting(configFilePath, "Config Version") || _configVersion == null || _configVersion.Value < 1)) { if (_positionOffsetX != null) { _positionOffsetX.Value = DefaultPositionOffset.x; } if (_positionOffsetY != null) { _positionOffsetY.Value = DefaultPositionOffset.y; } if (_positionOffsetZ != null) { _positionOffsetZ.Value = DefaultPositionOffset.z; } if (_configVersion != null) { _configVersion.Value = 1; } ((BaseUnityPlugin)this).Config.Save(); VerboseLog("Reset model position offsets to zero for the new baseline anchor."); } } catch (Exception ex) { Log.LogWarning((object)("Failed to normalize position baseline config values: " + ex.Message)); } } private void LoadAssets() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Texture2D val = LoadExternalIconTexture(); _bundledReplacementBaseScale = DefaultBundledReplacementBaseScale; string text = ResolveBundlePath(); RuntimeReplacementModel = null; Bundle = null; MochiPrefab = null; MochiMaterial = null; MochiTexture = val; MikuMainTexture = null; RuntimeMikuMaterial = null; if (File.Exists(text)) { if (!TryLoadReplacementBundle(text, val)) { Log.LogError((object)("Found ScallionMiku bundle but failed to initialize replacement from: " + text)); } } else { Log.LogError((object)("ScallionMiku bundle is missing. Bundle-only runtime is enabled, so no PMX fallback will be loaded: " + text)); } } private bool TryLoadReplacementBundle(string bundlePath, Texture2D externalIconTexture) { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) Bundle = AssetBundle.LoadFromFile(bundlePath); if ((Object)(object)Bundle == (Object)null) { Log.LogError((object)("Failed to load ScallionMiku AssetBundle: " + bundlePath)); return false; } RuntimeReplacementModel = null; MochiPrefab = LoadBundleAssetWithFallback<GameObject>("assets/葱音未来_by_翼月生/scallionmiku.prefab", PrefabNameHints); MochiMaterial = LoadBundleAssetWithFallback<Material>("assets/葱音未来_by_翼月生/materials/scallionmiku-8.shintai.mat", MaterialNameHints); MochiTexture = externalIconTexture ?? LoadBundleAssetWithFallback<Texture2D>("assets/葱音未来_by_翼月生/textures/身体.png", IconTextureNameHints); Texture2D val = LoadBundleAssetWithFallback<Texture2D>("assets/葱音未来_by_翼月生/textures/身体.png", MainTextureNameHints); MikuMainTexture = CreateReadableTexture(val) ?? val; if ((Object)(object)MochiPrefab == (Object)null) { Log.LogError((object)"Failed to load replacement prefab from asset bundle."); Bundle.Unload(false); Bundle = null; return false; } _bundledReplacementBaseScale = CalculateBundledReplacementBaseScale(MochiPrefab); ConfigureMochiMaterial(MikuMainTexture); RuntimeMikuMaterial = CreateRuntimeMikuMaterial(MikuMainTexture); ItemPatch.SanitizeLoadedPrefabRendererMaterials(MochiPrefab, "TryLoadReplacementBundle"); if ((Object)(object)RuntimeMikuMaterial == (Object)null) { Log.LogWarning((object)"Runtime fallback material was not created. The bundled material will be used when available."); } if ((Object)(object)MochiTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement icon texture."); } if ((Object)(object)MikuMainTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement main texture."); } VerboseLog("Loaded ScallionMiku replacement from asset bundle: " + bundlePath); return true; } private static Vector3 CalculateBundledReplacementBaseScale(GameObject prefab) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return DefaultBundledReplacementBaseScale; } Vector3 val; if (!TryCalculatePrefabBounds(prefab.transform, out var combinedBounds, out var rendererCount)) { ManualLogSource log = Log; val = DefaultBundledReplacementBaseScale; log.LogWarning((object)("Failed to calculate bundled prefab bounds. Falling back to default bundle base scale: " + ((Vector3)(ref val)).ToString("F4"))); return DefaultBundledReplacementBaseScale; } float num = Mathf.Max(((Bounds)(ref combinedBounds)).size.y, 0.0001f); float num2 = RuntimeReferenceVisibleSizeAtBaseScale.y * 0.78f * 1.5f; float num3 = Mathf.Clamp(num2 / num, 0.04f, 1.2f); Vector3 result = default(Vector3); ((Vector3)(ref result))..ctor(num3, num3, num3); string[] obj = new string[8] { "Auto-calculated ScallionMiku bundle base scale. rendererCount=", rendererCount.ToString(CultureInfo.InvariantCulture), ", prefabBoundsSize=", null, null, null, null, null }; val = ((Bounds)(ref combinedBounds)).size; obj[3] = ((Vector3)(ref val)).ToString("F4"); obj[4] = ", targetHeight="; obj[5] = num2.ToString("F4", CultureInfo.InvariantCulture); obj[6] = ", baseScale="; obj[7] = ((Vector3)(ref result)).ToString("F4"); VerboseLog(string.Concat(obj)); return result; } private static bool TryCalculatePrefabBounds(Transform root, out Bounds combinedBounds, out int rendererCount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) combinedBounds = default(Bounds); rendererCount = 0; if ((Object)(object)root == (Object)null) { return false; } bool hasBounds = false; Matrix4x4 worldToLocalMatrix = root.worldToLocalMatrix; MeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null)) { AppendTransformedBounds(worldToLocalMatrix, ((Component)val).transform.localToWorldMatrix, component.sharedMesh.bounds, ref combinedBounds, ref hasBounds); rendererCount++; } } } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)root).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.sharedMesh == (Object)null)) { Bounds localBounds = ((Renderer)val2).localBounds; Vector3 size = ((Bounds)(ref localBounds)).size; Bounds sourceBounds = ((((Vector3)(ref size)).sqrMagnitude > 1E-06f) ? ((Renderer)val2).localBounds : val2.sharedMesh.bounds); AppendTransformedBounds(worldToLocalMatrix, ((Component)val2).transform.localToWorldMatrix, sourceBounds, ref combinedBounds, ref hasBounds); rendererCount++; } } return hasBounds; } private static void AppendTransformedBounds(Matrix4x4 rootWorldToLocal, Matrix4x4 childLocalToWorld, Bounds sourceBounds, ref Bounds combinedBounds, ref bool hasBounds) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Matrix4x4 val = rootWorldToLocal * childLocalToWorld; Vector3 center = ((Bounds)(ref sourceBounds)).center; Vector3 extents = ((Bounds)(ref sourceBounds)).extents; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val2 = center + Vector3.Scale(extents, new Vector3((float)i, (float)j, (float)k)); Vector3 val3 = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val2); if (!hasBounds) { combinedBounds = new Bounds(val3, Vector3.zero); hasBounds = true; } else { ((Bounds)(ref combinedBounds)).Encapsulate(val3); } } } } } private static string ResolveBundlePath() { return Path.Combine(directory, "ScallionMiku"); } private Texture2D LoadExternalIconTexture() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) string text = Path.Combine(directory, "ScallionMikuUI.png"); if (!File.Exists(text)) { return null; } try { using FileStream fileStream = File.OpenRead(text); Bitmap val = new Bitmap((Stream)fileStream); try { int width = ((Image)val).Width; int height = ((Image)val).Height; Color32[] array = (Color32[])(object)new Color32[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Color pixel = val.GetPixel(j, height - 1 - i); array[i * width + j] = new Color32(pixel.R, pixel.G, pixel.B, pixel.A); } } Texture2D val2 = new Texture2D(width, height, (TextureFormat)4, false, false) { name = Path.GetFileNameWithoutExtension(text) }; val2.SetPixels32(array); ((Texture)val2).filterMode = (FilterMode)1; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).anisoLevel = 1; val2.Apply(false, false); return val2; } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { Log.LogWarning((object)("Failed to load external icon texture '" + text + "': " + ex.Message)); return null; } } internal static GameObject CreateReplacementVisualInstance(string name) { if (RuntimeReplacementModel != null) { return RuntimeReplacementModel.Instantiate(name); } if ((Object)(object)MochiPrefab == (Object)null) { return null; } return Object.Instantiate<GameObject>(MochiPrefab); } internal static void VerboseLog(string message) { } private static T LoadBundleAssetWithFallback<T>(string preferredPath, params string[] nameHints) where T : Object { if ((Object)(object)Bundle == (Object)null) { return default(T); } if (!string.IsNullOrEmpty(preferredPath)) { T val = Bundle.LoadAsset<T>(preferredPath); if ((Object)(object)val != (Object)null) { return val; } } string[] allAssetNames = Bundle.GetAllAssetNames(); if (allAssetNames != null) { foreach (string text in allAssetNames) { if (AssetNameLooksRelevant(text, preferredPath, nameHints)) { T val2 = Bundle.LoadAsset<T>(text); if ((Object)(object)val2 != (Object)null) { VerboseLog("Loaded fallback " + typeof(T).Name + " from bundle path: " + text); return val2; } } } } T[] array = Bundle.LoadAllAssets<T>(); if (array == null || array.Length == 0) { Log.LogWarning((object)("No " + typeof(T).Name + " assets found in bundle for requested path: " + preferredPath)); return default(T); } T val3 = FindAssetByObjectName(array, preferredPath, nameHints); if ((Object)(object)val3 != (Object)null) { VerboseLog("Loaded fallback " + typeof(T).Name + " by object name: " + ((Object)val3).name); return val3; } if (array.Length == 1) { Log.LogWarning((object)("Loaded only available " + typeof(T).Name + " asset as fallback: " + ((Object)array[0]).name)); return array[0]; } Log.LogWarning((object)("Unable to identify " + typeof(T).Name + " for requested path '" + preferredPath + "'. Candidates: " + string.Join(", ", Array.ConvertAll(array, (T asset) => (!((Object)(object)asset != (Object)null)) ? "<null>" : ((Object)asset).name)))); return default(T); } private static T FindAssetByObjectName<T>(T[] assets, string preferredPath, string[] nameHints) where T : Object { string needle = (string.IsNullOrEmpty(preferredPath) ? string.Empty : Path.GetFileNameWithoutExtension(preferredPath)); foreach (T val in assets) { if (!((Object)(object)val == (Object)null)) { string value = ((Object)val).name ?? string.Empty; if (NameMatches(value, needle) || NameMatchesAnyHint(value, nameHints)) { return val; } } } return default(T); } private static bool AssetNameLooksRelevant(string assetName, string preferredPath, string[] nameHints) { if (string.IsNullOrEmpty(assetName)) { return false; } if (!string.IsNullOrEmpty(preferredPath)) { if (assetName.Equals(preferredPath, StringComparison.OrdinalIgnoreCase)) { return true; } string fileName = Path.GetFileName(preferredPath); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(preferredPath); if (!string.IsNullOrEmpty(fileName) && assetName.EndsWith(fileName, StringComparison.OrdinalIgnoreCase)) { return true; } if (NameMatches(assetName, fileNameWithoutExtension)) { return true; } } return NameMatchesAnyHint(assetName, nameHints); } private static bool NameMatchesAnyHint(string value, string[] hints) { if (string.IsNullOrEmpty(value) || hints == null) { return false; } for (int i = 0; i < hints.Length; i++) { if (NameMatches(value, hints[i])) { return true; } } return false; } private static bool NameMatches(string value, string needle) { if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(needle)) { return false; } return value.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0; } private static void ConfigureMochiMaterial(Texture2D mikuMainTexture) { if ((Object)(object)MochiMaterial == (Object)null) { return; } if ((Object)(object)MochiMaterial.shader == (Object)null || !MochiMaterial.shader.isSupported) { Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"); if ((Object)(object)val != (Object)null) { MochiMaterial.shader = val; } } if ((Object)(object)mikuMainTexture != (Object)null) { ApplyTextureSet(MochiMaterial, mikuMainTexture); } ApplyMikuColorStyle(MochiMaterial); VerboseLog("Configured bundled material: " + ((Object)MochiMaterial).name); } private static bool TryAssignTextureIfMissing(Material material, string propertyName, Texture2D texture) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null || (Object)(object)texture == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return false; } try { if ((Object)(object)material.GetTexture(propertyName) != (Object)null) { return false; } material.SetTexture(propertyName, (Texture)(object)texture); material.SetTextureScale(propertyName, Vector2.one); material.SetTextureOffset(propertyName, Vector2.zero); return true; } catch (Exception ex) { VerboseLog("Skip texture assignment on material '" + ((Object)material).name + "', property '" + propertyName + "': " + ex.Message); return false; } } private static void TryAssignTextureIfMissing(Material material, string[] propertyNames, Texture2D texture) { if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null) && propertyNames != null) { for (int i = 0; i < propertyNames.Length; i++) { TryAssignTextureIfMissing(material, propertyNames[i], texture); } } } private static void ApplyTextureSet(Material material, Texture2D albedo) { if (!((Object)(object)material == (Object)null)) { TryAssignTextureIfMissing(material, PreferredTextureProps, albedo); ApplyMikuColorStyle(material); } } private static void ApplyMikuColorStyle(Material material) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Tint")) { material.SetColor("_Tint", MikuStyleTint); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", MikuStyleTint); } if (material.HasProperty("_Color")) { material.SetColor("_Color", MikuStyleTint); } if (material.HasProperty("_Smoothness")) { material.SetFloat("_Smoothness", 0.3f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0.3f); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_BumpScale")) { material.SetFloat("_BumpScale", 0f); } if (material.HasProperty("_OcclusionStrength")) { material.SetFloat("_OcclusionStrength", 0f); } if (material.HasProperty("_SpecularHighlights")) { material.SetFloat("_SpecularHighlights", 0f); } if (material.HasProperty("_EnvironmentReflections")) { material.SetFloat("_EnvironmentReflections", 0f); } if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static Texture2D CreateReadableTexture(Texture2D source) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown if ((Object)(object)source == (Object)null) { return null; } try { source.GetPixel(0, 0); return source; } catch { } RenderTexture temporary = RenderTexture.GetTemporary(((Texture)source).width, ((Texture)source).height, 0, (RenderTextureFormat)0); RenderTexture active = RenderTexture.active; try { Graphics.Blit((Texture)(object)source, temporary); RenderTexture.active = temporary; Texture2D val = new Texture2D(((Texture)source).width, ((Texture)source).height, (TextureFormat)4, true, false) { name = ((Object)source).name + "_Readable" }; val.ReadPixels(new Rect(0f, 0f, (float)((Texture)source).width, (float)((Texture)source).height), 0, 0); val.Apply(true, false); return val; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } private static Material CreateRuntimeMikuMaterial(Texture2D texture) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { Log.LogError((object)"Failed to create runtime material because no compatible shader was found."); return null; } Material val2 = new Material(val) { name = "Miku_RuntimeMaterial", renderQueue = 2000, color = Color.white }; if ((Object)(object)texture != (Object)null) { TryAssignTextureIfMissing(val2, "_BaseMap", texture); TryAssignTextureIfMissing(val2, "_MainTex", texture); } if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 0f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_ZWrite")) { val2.SetFloat("_ZWrite", 1f); } if (val2.HasProperty("_Cull")) { val2.SetFloat("_Cull", 0f); } val2.SetOverrideTag("RenderType", "Opaque"); val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.EnableKeyword("_SURFACE_TYPE_OPAQUE"); ApplyMikuColorStyle(val2); return val2; } } public class MikuMarker : MonoBehaviour { public bool HasAppliedState; public int LastRefreshRevision = -1; public int LastLayer = int.MinValue; public ItemState LastItemState; public bool LastShouldShow; public bool HiddenByOriginalRule; public Vector3 LastLocalPosition; public Quaternion LastLocalRotation = Quaternion.identity; public Vector3 LastLocalScale; } public class MikuCollisionMarker : MonoBehaviour { } public class MikuTwinTailClothState : MonoBehaviour { public int MeshInstanceId; public int MovableVertexCount; } public class MikuScaleRefreshGuard : MonoBehaviour { private bool _pendingRefresh; private bool _hardReset; private int _targetFrame = -1; private bool _clothSuspendedForPause; public void QueueRefresh(bool hardReset) { _pendingRefresh = true; _hardReset |= hardReset; _targetFrame = Mathf.Max(_targetFrame, Time.frameCount + 1); } private void LateUpdate() { bool flag = Time.timeScale <= 0.0001f; if (flag) { SuspendClothsForPause(); } else if (_clothSuspendedForPause) { ResumeClothsAfterPause(); } if (_pendingRefresh && Time.frameCount >= _targetFrame) { _pendingRefresh = false; _targetFrame = -1; RefreshSkinnedMeshes(); RefreshCloths(_hardReset || flag); _hardReset = false; } } private void RefreshSkinnedMeshes() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } val.updateWhenOffscreen = true; Vector3 size; Bounds val2; if ((Object)(object)val.sharedMesh != (Object)null) { Bounds bounds = val.sharedMesh.bounds; size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 1E-06f) { val2 = val.sharedMesh.bounds; goto IL_006b; } } val2 = ((Renderer)val).localBounds; goto IL_006b; IL_006b: Bounds localBounds = val2; size = ((Bounds)(ref localBounds)).size; if (((Vector3)(ref size)).sqrMagnitude > 1E-06f) { ((Bounds)(ref localBounds)).Expand(new Vector3(0.2f, 0.25f, 0.2f)); ((Renderer)val).localBounds = localBounds; } } } private void RefreshCloths(bool hardReset) { Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true); foreach (Cloth val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } val.ClearTransformMotion(); if (hardReset && val.enabled) { val.enabled = false; if (!_clothSuspendedForPause) { val.enabled = true; } } val.ClearTransformMotion(); } } private void SuspendClothsForPause() { Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true); foreach (Cloth val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.ClearTransformMotion(); if (val.enabled) { val.enabled = false; } } } _clothSuspendedForPause = true; } private void ResumeClothsAfterPause() { RefreshSkinnedMeshes(); Cloth[] componentsInChildren = ((Component)this).GetComponentsInChildren<Cloth>(true); foreach (Cloth val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.enabled = true; val.ClearTransformMotion(); } } _clothSuspendedForPause = false; } } public class MikuDeformGuard : MonoBehaviour { private const float SqueezeDuration = 0.78f; private const float SqueezeCompressPhase = 0.42f; private Transform[] _allTransforms = Array.Empty<Transform>(); private Vector3[] _initialChildScales = Array.Empty<Vector3>(); private Vector3 _rootLocalPosition; private Quaternion _rootLocalRotation; private Vector3 _rootLocalScale; private Item _boundItem; private bool _wasUsing; private float _squeezeElapsed = 0.78f; internal Item BoundItem => _boundItem; public void Initialize(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; _wasUsing = false; _squeezeElapsed = 0.78f; Capture(); } public void Bind(Item item) { _boundItem = item; } public void SetRootTarget(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; } private bool IsHeldAndUsing() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1) { if (!_boundItem.isUsingPrimary) { return _boundItem.isUsingSecondary; } return true; } return false; } private void UpdateSingleSqueezeState() { bool flag = IsHeldAndUsing(); if (flag && !_wasUsing) { _squeezeElapsed = 0f; } _wasUsing = flag; if (_squeezeElapsed < 0.78f) { _squeezeElapsed += Time.deltaTime; } } private float EvaluateSingleSqueezeWeight() { if (_squeezeElapsed >= 0.78f) { return 0f; } float num = Mathf.Clamp01(_squeezeElapsed / 0.78f); if (num <= 0.42f) { return Mathf.SmoothStep(0f, 1f, num / 0.42f); } float num2 = (num - 0.42f) / 0.58000004f; return Mathf.SmoothStep(1f, 0f, Mathf.Clamp01(num2)); } private Vector3 GetDesiredRootScale(float squeezeWeight) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (squeezeWeight <= 0.0005f) { return _rootLocalScale; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1f - 0.14f * squeezeWeight, 1f + 0.11f * squeezeWeight, 1f - 0.14f * squeezeWeight); return Vector3.Scale(_rootLocalScale, val); } public void Capture() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _allTransforms = ((Component)this).GetComponentsInChildren<Transform>(true); _initialChildScales = (Vector3[])(object)new Vector3[_allTransforms.Length]; for (int i = 0; i < _allTransforms.Length; i++) { _initialChildScales[i] = _allTransforms[i].localScale; } } private void LateUpdate() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) if (_allTransforms.Length == 0 || _allTransforms.Length != _initialChildScales.Length) { Capture(); } if (((Component)this).transform.localPosition != _rootLocalPosition) { ((Component)this).transform.localPosition = _rootLocalPosition; } if (((Component)this).transform.localRotation != _rootLocalRotation) { ((Component)this).transform.localRotation = _rootLocalRotation; } UpdateSingleSqueezeState(); float squeezeWeight = EvaluateSingleSqueezeWeight(); Vector3 desiredRootScale = GetDesiredRootScale(squeezeWeight); if (((Component)this).transform.localScale != desiredRootScale) { ((Component)this).transform.localScale = desiredRootScale; } for (int i = 0; i < _allTransforms.Length; i++) { Transform val = _allTransforms[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)((Component)this).transform) && val.localScale != _initialChildScales[i]) { val.localScale = _initialChildScales[i]; } } } } public class MikuRendererGuard : MonoBehaviour { private const float RefreshInterval = 0.1f; private float _nextRefreshTime; private Item _boundItem; private Renderer[] _cachedRenderers = Array.Empty<Renderer>(); internal Item BoundItem => _boundItem; public void Bind(Item item) { _boundItem = item; } private void LateUpdate() { if (!Plugin.ModEnabled || !Plugin.EnableVisibilityGuard) { return; } MikuMarker component = ((Component)this).GetComponent<MikuMarker>(); if ((Object)(object)component != (Object)null && component.HiddenByOriginalRule) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < _nextRefreshTime) { return; } _nextRefreshTime = realtimeSinceStartup + 0.1f; if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } int num = (((Object)(object)_boundItem != (Object)null) ? ((Component)_boundItem).gameObject.layer : ((Component)this).gameObject.layer); if (((Component)this).gameObject.layer != num) { ((Component)this).gameObject.layer = num; } Renderer[] renderableChildren = GetRenderableChildren(); foreach (Renderer val in renderableChildren) { if (!((Object)(object)val == (Object)null)) { EnsureRendererVisible(val, num); } } } private Renderer[] GetRenderableChildren() { if (_cachedRenderers.Length == 0 || HasNullRenderer(_cachedRenderers)) { _cachedRenderers = ((Component)this).GetComponentsInChildren<Renderer>(true); } return _cachedRenderers; } private static bool HasNullRenderer(Renderer[] renderers) { for (int i = 0; i < renderers.Length; i++) { if ((Object)(object)renderers[i] == (Object)null) { return true; } } return false; } private static void EnsureRendererVisible(Renderer renderer, int targetLayer) { if (!((Component)renderer).gameObject.activeSelf) { ((Component)renderer).gameObject.SetActive(true); } if (renderer.forceRenderingOff) { renderer.forceRenderingOff = false; } if (!renderer.enabled) { renderer.enabled = true; } renderer.SetPropertyBlock((MaterialPropertyBlock)null); ((Component)renderer).gameObject.layer = targetLayer; renderer.allowOcclusionWhenDynamic = false; ItemPatch.NormalizeRuntimeRendererMaterials(renderer, "RendererGuard"); } private static void NormalizeRendererMaterialColor(Renderer renderer) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) Material[] sharedMaterials = renderer.sharedMaterials; foreach (Material val in sharedMaterials) { if (!((Object)(object)val == (Object)null)) { Color white = Color.white; if (val.HasProperty("_Tint")) { val.SetColor("_Tint", white); } if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", white); } if (val.HasProperty("_Color")) { val.SetColor("_Color", white); } } } } } [HarmonyPatch(typeof(Item))] public class ItemPatch { private const int VisibleLayer = 0; private static readonly Color MikuMaterialTint = new Color(0.98f, 1f, 1f, 1f); private const string MikuVisualName = "MikuFumo_Visual"; private const string MikuCollisionName = "MikuCollisionProxy"; private static readonly Vector3 BaselineMikuLocalPosition = new Vector3(-0.06f, -0.5f, 0f); private static readonly Vector3 WorldMikuLocalPosition = BaselineMikuLocalPosition; private static readonly Quaternion WorldMikuLocalRotation = Quaternion.identity; private static readonly Quaternion BundledWorldMikuLocalRotation = Quaternion.Euler(0f, 180f, 0f); private static readonly Vector3 HeldMikuLocalPosition = BaselineMikuLocalPosition; private static readonly Quaternion HeldMikuLocalRotation = Quaternion.Euler(10f, 0f, 0f); private static readonly Quaternion BundledHeldMikuLocalRotation = Quaternion.Euler(10f, 180f, 0f); private const int TwinTailChainStartIndex = 3; private const int TwinTailChainEndIndex = 9; private const int TwinTailAnchorIndex = 2; private const float TwinTailMinInfluenceThreshold = 0.12f; private const float TwinTailMaxDistanceCap = 0.78f; private const float TwinTailStretchingStiffness = 0.98f; private const float TwinTailBendingStiffness = 0.9f; private const float TwinTailDamping = 0.2f; private const float TwinTailFriction = 0.2f; private const float TwinTailCollisionMassScale = 0.06f; private const float TwinTailSolverFrequency = 36f; private const float TwinTailWorldVelocityScale = 0.2f; private const float TwinTailWorldAccelerationScale = 0.75f; private const double SlowCreateProfileTotalThresholdMs = 12.0; private const double SlowCreateProfileStageThresholdMs = 4.0; private static readonly string[] UnwantedFootKeywords = new string[3] { "hand", "glove", "mitten" }; private static readonly string[] CollisionExcludedRendererKeywords = new string[8] { "hair", "tail", "twintail", "twin_tail", "pigtail", "ponytail", "bang", "ahoge" }; private static readonly FieldRef<Character, CharacterData> CharacterDataRef = AccessTools.FieldRefAccess<Character, CharacterData>("data"); private static readonly FieldRef<CharacterData, Item> CharacterCurrentItemRef = AccessTools.FieldRefAccess<CharacterData, Item>("_currentitem"); private static readonly HashSet<int> LoggedRuntimeRendererMaterialWarnings = new HashSet<int>(); private static bool SlowCreateProfileLogged; private static bool IsBingBong(Item item) { if ((Object)(object)item != (Object)null) { if (((Object)item).name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) < 0) { return ((Object)item).name.IndexOf("Bing Bong", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } internal static bool IsMikuTransform(Transform transform) { if ((Object)(object)transform != (Object)null) { if (!((Object)(object)((Component)transform).GetComponentInParent<MikuMarker>() != (Object)null)) { return (Object)(object)((Component)transform).GetComponentInParent<MikuCollisionMarker>() != (Object)null; } return true; } return false; } private static bool IsInBackpack(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 2; } return false; } private static bool IsHeld(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 1; } return false; } private static bool ShouldShowReplacement(Item item) { if ((Object)(object)item != (Object)null && Plugin.ModEnabled) { return !IsReplacementHiddenByOriginal(item); } return false; } private static bool IsReplacementHiddenByOriginal(Item item) { return IsReplacementHiddenByOriginal(FindMikuRoot(item)); } private static bool IsReplacementHiddenByOriginal(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return false; } MikuMarker component = ((Component)mikuRoot).GetComponent<MikuMarker>(); if ((Object)(object)component != (Object)null) { return component.HiddenByOriginalRule; } return false; } private static void SetReplacementHiddenByOriginal(Transform mikuRoot, bool hidden) { if (!((Object)(object)mikuRoot == (Object)null)) { MikuMarker component = ((Component)mikuRoot).GetComponent<MikuMarker>(); if ((Object)(object)component != (Object)null) { component.HiddenByOriginalRule = hidden; } } } private static void HideReplacementForOriginalRule(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { SetReplacementHiddenByOriginal(mikuRoot, hidden: true); Transform val = FindMikuCollisionRoot(item); SetColliderArrayEnabled(((Object)(object)val != (Object)null) ? GetUsableProxyColliders(val) : Array.Empty<Collider>(), enabled: false); DisableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); if (((Component)mikuRoot).gameObject.activeSelf) { ((Component)mikuRoot).gameObject.SetActive(false); } } } private static Vector3 ResolveScaleByState(Item item) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) float num = (IsInBackpack(item) ? Plugin.BackpackScaleMultiplier : Plugin.WorldScaleMultiplier); return Plugin.ReplacementBaseScale * num; } private static Vector3 ApplyPlayerFacingScale(Vector3 scale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) return new Vector3(0f - Mathf.Abs(scale.x), Mathf.Abs(scale.y), 0f - Mathf.Abs(scale.z)); } private static bool UseBundledPositiveFacing() { return Plugin.RuntimeReplacementModel == null; } private static Vector3 CompensateRuntimeScalePosition(Vector3 basePosition, Vector3 currentScale, Vector3 referenceScale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return basePosition; } private static void ResolvePoseByState(Item item, out Vector3 localPosition, out Quaternion localRotation, out Vector3 localScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ResolveScaleByState(item); if (IsHeld(item)) { bool flag = UseBundledPositiveFacing(); localRotation = (flag ? BundledHeldMikuLocalRotation : HeldMikuLocalRotation); localScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val)); Vector3 val2 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting; Vector3 referenceScale = (Vector3)(flag ? new Vector3(Mathf.Abs(val2.x), Mathf.Abs(val2.y), Mathf.Abs(val2.z)) : ApplyPlayerFacingScale(val2)); localPosition = CompensateRuntimeScalePosition(HeldMikuLocalPosition, localScale, referenceScale); } else if (IsInBackpack(item)) { localRotation = WorldMikuLocalRotation; localScale = val; Vector3 referenceScale2 = Plugin.ReplacementBaseScale * Plugin.DefaultBackpackScaleSetting; localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale2); } else { bool flag2 = UseBundledPositiveFacing(); localRotation = (flag2 ? BundledWorldMikuLocalRotation : WorldMikuLocalRotation); localScale = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val.x), Mathf.Abs(val.y), Mathf.Abs(val.z)) : ApplyPlayerFacingScale(val)); Vector3 val3 = Plugin.ReplacementBaseScale * Plugin.DefaultWorldScaleSetting; Vector3 referenceScale3 = (Vector3)(flag2 ? new Vector3(Mathf.Abs(val3.x), Mathf.Abs(val3.y), Mathf.Abs(val3.z)) : ApplyPlayerFacingScale(val3)); localPosition = CompensateRuntimeScalePosition(WorldMikuLocalPosition, localScale, referenceScale3); } localPosition += Plugin.PositionOffset; } private static Transform FindMikuRoot(Item item) { if ((Object)(object)item == (Object)null) { return null; } Transform val = ((Component)item).transform.Find("MikuFumo_Visual"); if ((Object)(object)val != (Object)null) { return val; } MikuMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren<MikuMarker>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { return ((Component)componentsInChildren[i]).transform; } } return null; } private static Transform FindMikuCollisionRoot(Item item) { if ((Object)(object)item == (Object)null) { return null; } Transform val = ((Component)item).transform.Find("MikuCollisionProxy"); if ((Object)(object)val != (Object)null) { return val; } MikuCollisionMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren<MikuCollisionMarker>(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { return ((Component)componentsInChildren[i]).transform; } } return null; } private static MikuExpressionController FindExpressionController(Transform mikuRoot) { if (!((Object)(object)mikuRoot != (Object)null)) { return null; } return ((Component)mikuRoot).GetComponentInChildren<MikuExpressionController>(true); } private static Item FindBoundItemFromMikuRoot(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return null; } MikuRendererGuard component = ((Component)mikuRoot).GetComponent<MikuRendererGuard>(); if ((Object)(object)component != (Object)null && (Object)(object)component.BoundItem != (Object)null) { return component.BoundItem; } MikuDeformGuard component2 = ((Component)mikuRoot).GetComponent<MikuDeformGuard>(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.BoundItem != (Object)null) { return component2.BoundItem; } MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot); if ((Object)(object)mikuExpressionController != (Object)null && (Object)(object)mikuExpressionController.BoundItem != (Object)null) { return mikuExpressionController.BoundItem; } return ((Component)mikuRoot).GetComponentInParent<Item>(); } private static MikuScaleRefreshGuard EnsureScaleRefreshGuard(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return null; } MikuScaleRefreshGuard mikuScaleRefreshGuard = ((Component)mikuRoot).GetComponent<MikuScaleRefreshGuard>(); if ((Object)(object)mikuScaleRefreshGuard == (Object)null) { mikuScaleRefreshGuard = ((Component)mikuRoot).gameObject.AddComponent<MikuScaleRefreshGuard>(); } return mikuScaleRefreshGuard; } private static void QueueScaleSensitiveRefresh(Transform mikuRoot, bool forceHardReset) { MikuScaleRefreshGuard mikuScaleRefreshGuard = EnsureScaleRefreshGuard(mikuRoot); if (!((Object)(object)mikuScaleRefreshGuard == (Object)null)) { bool flag = Time.timeScale <= 0.0001f; mikuScaleRefreshGuard.QueueRefresh(forceHardReset || flag); } } private static MikuExpressionController EnsureExpressionController(Transform mikuRoot) { MikuExpressionController mikuExpressionController = FindExpressionController(mikuRoot); if ((Object)(object)mikuExpressionController != (Object)null || (Object)(object)mikuRoot == (Object)null) { return mikuExpressionController; } SkinnedMeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren<SkinnedMeshRenderer>(true); List<SkinnedMeshRenderer> list = new List<SkinnedMeshRenderer>(); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && val.sharedMesh.blendShapeCount > 0) { list.Add(val); } } if (list.Count > 0) { MikuExpressionController mikuExpressionController2 = ((Component)mikuRoot).gameObject.AddComponent<MikuExpressionController>(); mikuExpressionController2.Initialize((IEnumerable<SkinnedMeshRenderer>)list); return mikuExpressionController2; } return null; } private static Texture GetMikuTexture() { if ((Object)(object)Plugin.MikuMainTexture != (Object)null) { return (Texture)(object)Plugin.MikuMainTexture; } Texture val = TryGetTexture(Plugin.MochiMaterial); if ((Object)(object)val != (Object)null) { return val; } return TryGetTexture(Plugin.RuntimeMikuMaterial); } private static Texture TryGetTexture(Material material) { if ((Object)(object)material == (Object)null) { return null; } if (material.HasProperty("_BaseMap")) { Texture texture = material.GetTexture("_BaseMap"); if ((Object)(object)texture != (Object)null) { return texture; } } if (material.HasProperty("_MainTex")) { return material.GetTexture("_MainTex"); } return null; } private static bool TrySetTextureSafe(Material material, string propertyName, Texture texture) { if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return false; } try { material.SetTexture(propertyName, texture); return true; } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Skip SetTexture on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message); return false; } } private static void TrySetTextureTransformSafe(Material material, string propertyName, Vector2 scale, Vector2 offset) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null || string.IsNullOrEmpty(propertyName) || !material.HasProperty(propertyName)) { return; } try { material.SetTextureScale(propertyName, scale); material.SetTextureOffset(propertyName, offset); } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Skip texture transform on material '" + ((Object)material).name + "' property '" + propertyName + "': " + ex.Message); } } private static void ApplyMikuTextureSafe(Material material, Texture mikuTexture) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null) && !((Object)(object)mikuTexture == (Object)null)) { if (TrySetTextureSafe(material, "_BaseMap", mikuTexture)) { TrySetTextureTransformSafe(material, "_BaseMap", Vector2.one, Vector2.zero); } if (TrySetTextureSafe(material, "_MainTex", mikuTexture)) { TrySetTextureTransformSafe(material, "_MainTex", Vector2.one, Vector2.zero); } } } private static void DisableOptionalSurfaceTextures(Material material) { if (!((Object)(object)material == (Object)null)) { TrySetTextureSafe(material, "_BumpMap", null); TrySetTextureSafe(material, "_NormalMap", null); TrySetTextureSafe(material, "_OcclusionMap", null); TrySetTextureSafe(material, "_MetallicGlossMap", null); TrySetTextureSafe(material, "_SpecGlossMap", null); material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static void OptimizeTextureSampling(Texture texture) { Texture2D val = (Texture2D)(object)((texture is Texture2D) ? texture : null); if (!((Object)(object)val == (Object)null)) { ((Texture)val).filterMode = (FilterMode)2; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).anisoLevel = Mathf.Max(((Texture)val).anisoLevel, 16); ((Texture)val).mipMapBias = Mathf.Min(((Texture)val).mipMapBias, -0.75f); } } private static void ApplyRealisticMaterialTuning(Material material) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { Color val = ResolveMaterialTint(material); val.a = 1f; if (material.HasProperty("_Tint")) { material.SetColor("_Tint", val); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", val); } if (material.HasProperty("_Color")) { material.SetColor("_Color", val); } if (material.HasProperty("_Smoothness")) { material.SetFloat("_Smoothness", 0.3f); } if (material.HasProperty("_Glossiness")) { material.SetFloat("_Glossiness", 0.3f); } if (material.HasProperty("_Metallic")) { material.SetFloat("_Metallic", 0f); } if (material.HasProperty("_BumpScale")) { material.SetFloat("_BumpScale", 0f); } if (material.HasProperty("_OcclusionStrength")) { material.SetFloat("_OcclusionStrength", 0f); } if (material.HasProperty("_SpecularHighlights")) { material.SetFloat("_SpecularHighlights", 0f); } if (material.HasProperty("_EnvironmentReflections")) { material.SetFloat("_EnvironmentReflections", 0f); } DisableOptionalSurfaceTextures(material); if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", Color.black); material.DisableKeyword("_EMISSION"); } } } private static Material CreateFallbackMaterial() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { return null; } return new Material(val) { color = Color.white }; } private static Color ResolveMaterialTint(Material material) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { return MikuMaterialTint; } if (material.HasProperty("_Tint")) { return material.GetColor("_Tint"); } if (material.HasProperty("_BaseColor")) { return material.GetColor("_BaseColor"); } if (material.HasProperty("_Color")) { return material.GetColor("_Color"); } return MikuMaterialTint; } private static void OptimizeMaterialTextureSampling(Material material) { OptimizeTextureSampling(TryGetTexture(material)); } private static Material CreateRendererMaterialInstance(Material template = null) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) template = template ?? Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial; bool flag = Plugin.RuntimeReplacementModel == null; if ((Object)(object)template == (Object)null) { Material val = CreateFallbackMaterial(); if ((Object)(object)val == (Object)null) { return null; } template = val; } Material val2; if (flag) { val2 = new Material(template); if ((Object)(object)val2.shader == (Object)null || !val2.shader.isSupported) { Material val3 = CreateFallbackMaterial(); if ((Object)(object)val3 != (Object)null) { Texture obj = TryGetTexture(template); Texture mikuTexture = GetMikuTexture(); if (obj == null) { obj = mikuTexture; } Texture val4 = obj; Color val5 = ResolveMaterialTint(template); val5.a = 1f; val2 = val3; if ((Object)(object)val4 != (Object)null) { OptimizeTextureSampling(val4); ApplyMikuTextureSafe(val2, val4); } if (val2.HasProperty("_Tint")) { val2.SetColor("_Tint", val5); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val5); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val5); } } } } else { val2 = new Material(template); } if ((Object)(object)val2 == (Object)null) { return null; } ((Object)val2).name = (((Object)(object)template != (Object)null) ? ((Object)template).name : "MikuMaterial") + "_Runtime"; Texture val6 = (((Object)(object)template != (Object)null) ? TryGetTexture(template) : TryGetTexture(val2)); Texture mikuTexture2 = GetMikuTexture(); if ((Object)(object)val6 != (Object)null) { OptimizeTextureSampling(val6); ApplyMikuTextureSafe(val2, val6); } else if ((Object)(object)mikuTexture2 != (Object)null) { OptimizeTextureSampling(mikuTexture2); ApplyMikuTextureSafe(val2, mikuTexture2); } Color val7 = ResolveMaterialTint(template); val7.a = 1f; if (val2.HasProperty("_Tint")) { val2.SetColor("_Tint", val7); } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val7); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", val7); } DisableOptionalSurfaceTextures(val2); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 0f); } if (val2.HasProperty("_Blend")) { val2.SetFloat("_Blend", 0f); } if (val2.HasProperty("_ZWrite")) { val2.SetFloat("_ZWrite", 1f); } if (val2.HasProperty("_SrcBlend")) { val2.SetFloat("_SrcBlend", 1f); } if (val2.HasProperty("_DstBlend")) { val2.SetFloat("_DstBlend", 0f); } if (val2.HasProperty("_Cull")) { val2.SetFloat("_Cull", 0f); } if (val2.HasProperty("_AlphaClip")) { val2.SetFloat("_AlphaClip", 0f); } if (val2.HasProperty("_Cutoff")) { val2.SetFloat("_Cutoff", 0f); } if (val2.HasProperty("_LOD")) { val2.SetFloat("_LOD", 600f); } val2.renderQueue = 2000; val2.SetOverrideTag("RenderType", "Opaque"); val2.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); val2.EnableKeyword("_SURFACE_TYPE_OPAQUE"); val2.DisableKeyword("_ALPHATEST_ON"); val2.DisableKeyword("_ALPHABLEND_ON"); val2.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val2.DisableKeyword("LOD_FADE_CROSSFADE"); ApplyRealisticMaterialTuning(val2); return val2; } private static Material[] BuildMaterialArray(Material[] sourceMaterials, int subMeshCount) { int num = Mathf.Max(1, subMeshCount); Material[] array = (Material[])(object)new Material[num]; for (int i = 0; i < num; i++) { Material val = CreateRendererMaterialInstance((sourceMaterials != null && i < sourceMaterials.Length) ? sourceMaterials[i] : null); if ((Object)(object)val == (Object)null) { val = CreateFallbackMaterial(); } if ((Object)(object)val != (Object)null) { Texture val2 = TryGetTexture(val); if ((Object)(object)val2 == (Object)null) { Texture mikuTexture = GetMikuTexture(); if ((Object)(object)mikuTexture != (Object)null) { OptimizeTextureSampling(mikuTexture); ApplyMikuTextureSafe(val, mikuTexture); } } else { OptimizeTextureSampling(val2); } DisableOptionalSurfaceTextures(val); ApplyRealisticMaterialTuning(val); } array[i] = val; } return array; } private static Material ResolveRendererMaterialSlot(Material[] sourceMaterials, Material[] runtimeTemplateMaterials, int index, Material lastResolvedMaterial) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown Material val = ((sourceMaterials != null && index < sourceMaterials.Length) ? sourceMaterials[index] : null); if ((Object)(object)val != (Object)null) { return val; } Material val2 = ((runtimeTemplateMaterials.Length != 0) ? runtimeTemplateMaterials[Mathf.Min(index, runtimeTemplateMaterials.Length - 1)] : null); Material val3 = CreateRendererMaterialInstance(val2); if ((Object)(object)val3 == (Object)null && (Object)(object)val2 != (Object)null) { val3 = new Material(val2); } if ((Object)(object)val3 != (Object)null) { return val3; } if ((Object)(object)lastResolvedMaterial != (Object)null) { return lastResolvedMaterial; } Material val4 = Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial; if ((Object)(object)val4 != (Object)null) { val3 = CreateRendererMaterialInstance(val4); if ((Object)(object)val3 == (Object)null) { val3 = new Material(val4); } } return val3 ?? CreateFallbackMaterial(); } private static Material[] NormalizeRuntimeMaterialArray(Material[] sourceMaterials, int subMeshCount) { int num = Mathf.Max(1, subMeshCount); Material[] array = (Material[])(object)new Material[num]; Material[] runtimeTemplateMaterials = ((Plugin.RuntimeReplacementModel != null) ? Plugin.RuntimeReplacementModel.Materials : Array.Empty<Material>()); Material lastResolvedMaterial = null; for (int i = 0; i < num; i++) { Material val = (array[i] = ResolveRendererMaterialSlot(sourceMaterials, runtimeTemplateMaterials, i, lastResolvedMaterial)); if ((Object)(object)val != (Object)null) { lastResolvedMaterial = val; } } return array; } private static int GetRendererSubMeshCount(Renderer renderer) { MeshRenderer val = (MeshRenderer)(object)((renderer is MeshRenderer) ? renderer : null); if (val != null) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { return Mathf.Max(1, component.sharedMesh.subMeshCount); } } SkinnedMeshRenderer val2 = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val2 != null && (Object)(object)val2.sharedMesh != (Object)null) { return Mathf.Max(1, val2.sharedMesh.subMeshCount); } return 0; } private static string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return "<null>"; } List<string> list = new List<string>(); Transform val = transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list.ToArray()); } private static bool ShouldNormalizeRuntimeMaterialArray(Material[] materials, int subMeshCount) { if (subMeshCount <= 0) { return false; } if (materials == null || materials.Length != subMeshCount) { return true; } for (int i = 0; i < materials.Length; i++) { if ((Object)(object)materials[i] == (Object)null) { return true; } } return false; } internal static bool NormalizeRuntimeRendererMaterials(Renderer renderer, string context) { //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return false; } int rendererSubMeshCount = GetRendererSubMeshCount(renderer); if (rendererSubMeshCount <= 0) { return false; } Material[] sharedMaterials; try { sharedMaterials = renderer.sharedMaterials; } catch (Exception ex) { Plugin.VerboseLog("[ItemPatch] Failed to inspect renderer materials at " + context + ": " + ex.Message); return false; } if (!ShouldNormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount)) { return false; } int num = ((sharedMaterials != null) ? sharedMaterials.Length : 0); try { renderer.sharedMaterials = NormalizeRuntimeMaterialArray(sharedMaterials, rendererSubMeshCount); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[ItemPatch] Failed to correct renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", error=" + ex2.Message)); return false; } SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null); if (val != null && (Object)(object)val.sharedMesh != (Object)null) { Bounds bounds = val.sharedMesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)val).localBounds = bounds; } int instanceID = ((Object)renderer).GetInstanceID(); if (!LoggedRuntimeRendererMaterialWarnings.Contains(instanceID) && Plugin.Log != null) { LoggedRuntimeRendererMaterialWarnings.Add(instanceID); Plugin.VerboseLog("[ItemPatch] Corrected runtime renderer material layout at " + context + ": path=" + GetTransformPath(((Component)renderer).transform) + ", type=" + ((object)renderer).GetType().Name + ", subMeshes=" + rendererSubMeshCount + ", sharedMaterials(before)=" + num + ", sharedMaterials(after)=" + renderer.sharedMaterials.Length); } return true; } internal static int NormalizeRuntimeRendererMaterials(Renderer[] renderers, string context) { if (renderers == null || renderers.Length == 0) { return 0; } int num = 0; for (int i = 0; i < renderers.Length; i++) { if (NormalizeRuntimeRendererMaterials(renderers[i], context)) { num++; } } return num; } internal static void SanitizeLoadedPrefabRendererMaterials(GameObject prefabRoot, string context) { if (!((Object)(object)prefabRoot == (Object)null)) { int num = NormalizeRuntimeRendererMaterials(prefabRoot.GetComponentsInChildren<Renderer>(true), context); if (num > 0) { Plugin.VerboseLog("[ItemPatch] Corrected " + num.ToString(CultureInfo.InvariantCulture) + " prefab renderer material layouts at " + context + " for " + ((