using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("MikuFufu2")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.0.0")] [assembly: AssemblyInformationalVersion("2.0.0")] [assembly: AssemblyProduct("MikuFufu2")] [assembly: AssemblyTitle("MikuFufu2")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public sealed class IgnoresAccessChecksToAttribute : Attribute { private readonly string _assemblyName; public string AssemblyName => _assemblyName; public IgnoresAccessChecksToAttribute(string assemblyName) { _assemblyName = assemblyName; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] public sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte value) { NullableFlags = new byte[1] { value }; } public NullableAttribute(byte[] value) { NullableFlags = value; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] public sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte value) { Flag = value; } } [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int version) { Version = version; } } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class BepInAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public BepInAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)] public sealed class PatcherAutoPluginAttribute : Attribute { private string _guid; private string _name; private string _version; public string GUID { get { return _guid; } set { _guid = value; } } public string Name { get { return _name; } set { _name = value; } } public string Version { get { return _version; } set { _version = value; } } public PatcherAutoPluginAttribute(string guid = null, string name = null, string version = null) { _guid = guid; _name = name; _version = version; } } } namespace MikuBongFix { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.github.Thanks.MikuFufu2", "MikuFufu2", "2.0.0")] public class Plugin : BaseUnityPlugin { private static readonly string[] LegacyPluginIds = new string[2] { "com.github.Thanks.MikuBongFix", "com.github.FelineEntity.MikuBongFix" }; private const string BundleFileName = "mikupeak"; private const string RuntimeReplacementFolderName = "FUFU"; private const string ExternalIconFileName = "Fufu2.png"; private const string PrefabAssetPath = "assets/mikufumo/mikufumo.prefab"; private const string MaterialAssetPath = "assets/mikufumo/m_mikufumo.mat"; private const string IconTextureAssetPath = "assets/mikufumo/miku_icon.png"; private const string MainTextureAssetPath = "assets/mikufumo/miku.png"; private const string ConfigSection = "Main"; private const float WorldMinScaleMultiplier = 0.4f; private const float WorldMaxScaleMultiplier = 1.1f; private const float BackpackMinScaleMultiplier = 0.2f; private const float BackpackMaxScaleMultiplier = 1f; private const float DefaultWorldScaleMultiplier = 0.9f; private const float DefaultBackpackScaleMultiplier = 0.4f; private const string DefaultExpressionName = "None"; private const float DefaultExpressionWeight = 1f; private static readonly Vector3 DefaultReplacementBaseScale = new Vector3(1.5f, 1.5f, 1.5f); private static readonly string[] PreferredTextureProps = new string[2] { "_BaseMap", "_MainTex" }; private static readonly string[] PrefabNameHints = new string[3] { "mikufumo", "miku", "fumo" }; private static readonly string[] MaterialNameHints = new string[3] { "m_mikufumo", "mikufumo", "miku" }; private static readonly string[] IconTextureNameHints = new string[3] { "miku_icon", "icon", "miku" }; private static readonly string[] MainTextureNameHints = new string[3] { "miku", "mikufumo", "albedo" }; private static readonly Color MikuStyleTint = new Color(0.98f, 1f, 1f, 1f); private static ConfigEntry _modEnabled; private static ConfigEntry _worldScaleMultiplier; private static ConfigEntry _backpackScaleMultiplier; private static ManualLogSource _log; private static AssetBundle _bundle; private static GameObject _mochiPrefab; private static Material _mochiMaterial; private static Material _runtimeMikuMaterial; private static Texture2D _mochiTexture; private static Texture2D _mikuMainTexture; private static RuntimeReplacementModel _runtimeReplacementModel; public const string Name = "MikuFufu2"; public const string Id = "com.github.Thanks.MikuFufu2"; public const string Version = "2.0.5"; internal static Harmony Harmony = new Harmony("com.github.Thanks.MikuFufu2"); 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 BackpackScaleMultiplier { get { if (_backpackScaleMultiplier != null) { return Mathf.Clamp(_backpackScaleMultiplier.Value, 0.2f, 1f); } return 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 DefaultReplacementBaseScale * 0.78f * 1.5f; } return RuntimeReplacementModel.RecommendedBaseScale * 0.78f * 1.5f; } } internal static string ExpressionName => "None"; internal static float ExpressionWeight => 1f; internal static string ReplacementDisplayName { get { if (RuntimeReplacementModel == null) { return "Miku"; } return RuntimeReplacementModel.DisplayName; } } internal static string directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; MigrateLegacyConfigIfNeeded(); InitializeConfig(); LoadAssets(); try { Harmony.PatchAll(Assembly.GetExecutingAssembly()); } catch (Exception ex) { Log.LogError((object)("Failed to apply Harmony patches: " + ex)); } } private void MigrateLegacyConfigIfNeeded() { try { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; 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(); Log.LogInfo((object)("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 _modEnabled = ((BaseUnityPlugin)this).Config.Bind("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())); _worldScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind("Main", "Fufu Size In World", 0.9f, new ConfigDescription("Scale multiplier for Fufu while held or lying in the world.", (AcceptableValueBase)(object)new AcceptableValueRange(0.4f, 1.1f), Array.Empty())); _backpackScaleMultiplier = ((BaseUnityPlugin)this).Config.Bind("Main", "Fufu Size In Backpack", 0.4f, new ConfigDescription("Scale multiplier for the Fufu replacement while stored in the backpack.", (AcceptableValueBase)(object)new AcceptableValueRange(0.2f, 1f), Array.Empty())); } private void LoadAssets() { Texture2D val = LoadExternalIconTexture(); RuntimeReplacementModel = RuntimePmxLoader.Load(Path.Combine(directory, "FUFU"), Log); if (RuntimeReplacementModel != null) { MochiPrefab = null; Bundle = null; MochiTexture = val ?? RuntimeReplacementModel.IconTexture ?? RuntimeReplacementModel.PrimaryTexture; MikuMainTexture = RuntimeReplacementModel.PrimaryTexture; MochiMaterial = RuntimeReplacementModel.PrimaryMaterial; RuntimeMikuMaterial = RuntimeReplacementModel.PrimaryMaterial ?? CreateRuntimeMikuMaterial(MikuMainTexture); Log.LogInfo((object)("Loaded runtime FUFU replacement from folder: " + Path.Combine(directory, "FUFU"))); return; } string text = Path.Combine(directory, "mikupeak"); Bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)Bundle == (Object)null) { Log.LogError((object)("Failed to load runtime FUFU assets and failed to load AssetBundle: " + text)); return; } MochiPrefab = LoadBundleAssetWithFallback("assets/mikufumo/mikufumo.prefab", PrefabNameHints); MochiMaterial = LoadBundleAssetWithFallback("assets/mikufumo/m_mikufumo.mat", MaterialNameHints); MochiTexture = val ?? LoadBundleAssetWithFallback("assets/mikufumo/miku_icon.png", IconTextureNameHints); Texture2D val2 = LoadBundleAssetWithFallback("assets/mikufumo/miku.png", MainTextureNameHints); MikuMainTexture = CreateReadableTexture(val2) ?? val2; if ((Object)(object)MochiPrefab == (Object)null) { Log.LogError((object)"Failed to load replacement prefab from asset bundle."); return; } ConfigureMochiMaterial(MikuMainTexture); RuntimeMikuMaterial = CreateRuntimeMikuMaterial(MikuMainTexture); if ((Object)(object)RuntimeMikuMaterial == (Object)null) { Log.LogWarning((object)"Runtime fallback material was not created. The bundled material will be used when available."); } if ((Object)(object)MochiTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement icon texture."); } if ((Object)(object)MikuMainTexture == (Object)null) { Log.LogWarning((object)"Failed to load replacement main texture."); } } private Texture2D LoadExternalIconTexture() { //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, "Fufu2.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(MochiPrefab); } internal static void VerboseLog(string message) { } private static T LoadBundleAssetWithFallback(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(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(text); if ((Object)(object)val2 != (Object)null) { Log.LogWarning((object)("Loaded fallback " + typeof(T).Name + " from bundle path: " + text)); return val2; } } } } T[] array = Bundle.LoadAllAssets(); if (array == null || array.Length == 0) { Log.LogWarning((object)("No " + typeof(T).Name + " assets found in bundle for requested path: " + preferredPath)); return default(T); } T val3 = FindAssetByObjectName(array, preferredPath, nameHints); if ((Object)(object)val3 != (Object)null) { Log.LogWarning((object)("Loaded fallback " + typeof(T).Name + " by object name: " + ((Object)val3).name)); return val3; } if (array.Length == 1) { Log.LogWarning((object)("Loaded only available " + typeof(T).Name + " asset as fallback: " + ((Object)array[0]).name)); return array[0]; } Log.LogWarning((object)("Unable to identify " + typeof(T).Name + " for requested path '" + preferredPath + "'. Candidates: " + string.Join(", ", Array.ConvertAll(array, (T asset) => (!((Object)(object)asset != (Object)null)) ? "" : ((Object)asset).name)))); return default(T); } private static T FindAssetByObjectName(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 class MikuDeformGuard : MonoBehaviour { private const float SqueezeDuration = 0.78f; private const float SqueezeCompressPhase = 0.42f; private Transform[] _allTransforms = Array.Empty(); private Vector3[] _initialChildScales = Array.Empty(); private Vector3 _rootLocalPosition; private Quaternion _rootLocalRotation; private Vector3 _rootLocalScale; private Item _boundItem; private bool _wasUsing; private float _squeezeElapsed = 0.78f; public void Initialize(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; _wasUsing = false; _squeezeElapsed = 0.78f; Capture(); } public void Bind(Item item) { _boundItem = item; } public void SetRootTarget(Vector3 rootLocalPosition, Quaternion rootLocalRotation, Vector3 rootLocalScale) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _rootLocalPosition = rootLocalPosition; _rootLocalRotation = rootLocalRotation; _rootLocalScale = rootLocalScale; } private bool IsHeldAndUsing() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if ((Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1) { if (!_boundItem.isUsingPrimary) { return _boundItem.isUsingSecondary; } return true; } return false; } private void UpdateSingleSqueezeState() { bool flag = IsHeldAndUsing(); if (flag && !_wasUsing) { _squeezeElapsed = 0f; } _wasUsing = flag; if (_squeezeElapsed < 0.78f) { _squeezeElapsed += Time.deltaTime; } } private float EvaluateSingleSqueezeWeight() { if (_squeezeElapsed >= 0.78f) { return 0f; } float num = Mathf.Clamp01(_squeezeElapsed / 0.78f); if (num <= 0.42f) { return Mathf.SmoothStep(0f, 1f, num / 0.42f); } float num2 = (num - 0.42f) / 0.58000004f; return Mathf.SmoothStep(1f, 0f, Mathf.Clamp01(num2)); } private Vector3 GetDesiredRootScale(float squeezeWeight) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (squeezeWeight <= 0.0005f) { return _rootLocalScale; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(1f - 0.14f * squeezeWeight, 1f + 0.11f * squeezeWeight, 1f - 0.14f * squeezeWeight); return Vector3.Scale(_rootLocalScale, val); } public void Capture() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) _allTransforms = ((Component)this).GetComponentsInChildren(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(); public void Bind(Item item) { _boundItem = item; } private void LateUpdate() { if (!Plugin.ModEnabled || !Plugin.EnableVisibilityGuard || Time.time < _nextRefreshTime) { return; } _nextRefreshTime = Time.time + 0.1f; if (!((Component)this).gameObject.activeSelf) { ((Component)this).gameObject.SetActive(true); } int num = (((Object)(object)_boundItem != (Object)null) ? ((Component)_boundItem).gameObject.layer : ((Component)this).gameObject.layer); if (((Component)this).gameObject.layer != num) { ((Component)this).gameObject.layer = num; } Renderer[] renderableChildren = GetRenderableChildren(); foreach (Renderer val in renderableChildren) { if (!((Object)(object)val == (Object)null)) { EnsureRendererVisible(val, num); } } } private Renderer[] GetRenderableChildren() { if (_cachedRenderers.Length == 0 || HasNullRenderer(_cachedRenderers)) { _cachedRenderers = ((Component)this).GetComponentsInChildren(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; } 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 static readonly Vector3 WorldMikuLocalPosition = new Vector3(0f, 0.2f, 0.1f); private static readonly Quaternion WorldMikuLocalRotation = Quaternion.identity; private static readonly Vector3 HeldMikuLocalPosition = new Vector3(0f, -0.1f, 0.45f); private static readonly Quaternion HeldMikuLocalRotation = Quaternion.Euler(10f, 0f, 0f); private static readonly string[] UnwantedFootKeywords = new string[3] { "hand", "glove", "mitten" }; private static bool IsBingBong(Item item) { if ((Object)(object)item != (Object)null) { return ((Object)item).name.IndexOf("BingBong", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } internal static bool IsMikuTransform(Transform transform) { if ((Object)(object)transform != (Object)null) { return (Object)(object)((Component)transform).GetComponentInParent() != (Object)null; } return false; } private static bool IsInBackpack(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 2; } return false; } private static bool IsHeld(Item item) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)item != (Object)null) { return (int)item.itemState == 1; } return false; } private static bool ShouldShowReplacement(Item item) { if ((Object)(object)item != (Object)null) { return Plugin.ModEnabled; } return false; } private static 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 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_0010: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0020: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0075: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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) Vector3 val = ResolveScaleByState(item); if (IsHeld(item)) { localPosition = HeldMikuLocalPosition; localRotation = HeldMikuLocalRotation; localScale = ApplyPlayerFacingScale(val); } else if (IsInBackpack(item)) { localPosition = WorldMikuLocalPosition; localRotation = WorldMikuLocalRotation; localScale = val; } else { localPosition = WorldMikuLocalPosition; localRotation = WorldMikuLocalRotation; localScale = ApplyPlayerFacingScale(val); } } private static Transform FindMikuRoot(Item item) { if ((Object)(object)item == (Object)null) { return null; } MikuMarker[] componentsInChildren = ((Component)item).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { return ((Component)componentsInChildren[i]).transform; } } return ((Component)item).transform.Find("MikuFumo_Visual"); } private static MikuExpressionController FindExpressionController(Transform mikuRoot) { if (!((Object)(object)mikuRoot != (Object)null)) { return null; } return ((Component)mikuRoot).GetComponentInChildren(true); } 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown template = template ?? Plugin.RuntimeMikuMaterial ?? Plugin.MochiMaterial; if ((Object)(object)template == (Object)null) { Material val = CreateFallbackMaterial(); if ((Object)(object)val == (Object)null) { return null; } template = val; } Material val2 = new Material(template); Texture val3 = TryGetTexture(val2); Texture mikuTexture = GetMikuTexture(); if ((Object)(object)val3 != (Object)null) { OptimizeTextureSampling(val3); } else if ((Object)(object)mikuTexture != (Object)null) { OptimizeTextureSampling(mikuTexture); ApplyMikuTextureSafe(val2, mikuTexture); } 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 template = null; if (sourceMaterials != null && sourceMaterials.Length != 0) { template = sourceMaterials[Mathf.Min(i, sourceMaterials.Length - 1)]; } Material val = CreateRendererMaterialInstance(template); 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 void ApplyMaterialToMeshRenderer(MeshRenderer renderer) { int subMeshCount = 1; MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.sharedMesh != (Object)null) { subMeshCount = Mathf.Max(1, component.sharedMesh.subMeshCount); } ((Renderer)renderer).sharedMaterials = BuildMaterialArray(((Renderer)renderer).sharedMaterials, subMeshCount); } private static void ApplyMaterialToSkinnedRenderer(SkinnedMeshRenderer renderer) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) int subMeshCount = 1; if ((Object)(object)renderer.sharedMesh != (Object)null) { subMeshCount = Mathf.Max(1, renderer.sharedMesh.subMeshCount); } ((Renderer)renderer).sharedMaterials = BuildMaterialArray(((Renderer)renderer).sharedMaterials, subMeshCount); if ((Object)(object)renderer.sharedMesh != (Object)null) { Bounds bounds = renderer.sharedMesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)renderer).localBounds = bounds; } } private static bool HasVisibleReplacementRenderers(Transform mikuRoot) { if ((Object)(object)mikuRoot == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } for (int j = 0; j < sharedMaterials.Length; j++) { if ((Object)(object)sharedMaterials[j] != (Object)null) { return true; } } } return false; } private static void DisableOriginalRenderers(Item item) { Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = false; } } } private static void EnableOriginalRenderers(Item item) { Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = true; } } } private static void EnableOriginalColliders(Item item) { Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); List list = new List(); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = true; list.Add(val); } } if ((Object)(object)item != (Object)null) { item.colliders = list.ToArray(); } } private static void DisableOriginalColliders(Item item) { Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { val.enabled = false; } } } private static Collider FindColliderTemplate(Item item) { if ((Object)(object)item == (Object)null) { return null; } Collider[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null && !IsMikuTransform(((Component)val).transform)) { return val; } } return null; } private static Vector3 ClampColliderSize(Vector3 size) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) return new Vector3(Mathf.Max(size.x, 0.02f), Mathf.Max(size.y, 0.02f), Mathf.Max(size.z, 0.02f)); } private static bool HasNegativeScaleInHierarchy(Transform transform) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) Transform val = transform; while ((Object)(object)val != (Object)null) { Vector3 localScale = val.localScale; if (localScale.x < 0f || localScale.y < 0f || localScale.z < 0f) { return true; } val = val.parent; } return false; } private static void CopyColliderSettings(Collider source, Collider target) { if (!((Object)(object)target == (Object)null)) { if ((Object)(object)source != (Object)null) { target.isTrigger = source.isTrigger; target.sharedMaterial = source.sharedMaterial; target.contactOffset = source.contactOffset; } target.enabled = true; } } private static Collider AddConvexMeshColliderForMeshRenderer(MeshRenderer renderer, Collider templateCollider) { if ((Object)(object)renderer == (Object)null) { return null; } MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } MeshCollider val = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)renderer).gameObject.AddComponent(); } val.sharedMesh = null; val.convex = true; val.sharedMesh = component.sharedMesh; CopyColliderSettings(templateCollider, (Collider)(object)val); return (Collider)(object)val; } private static Collider AddBoxColliderForMeshRenderer(MeshRenderer renderer, Collider templateCollider) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return null; } if (HasNegativeScaleInHierarchy(((Component)renderer).transform)) { return null; } MeshFilter component = ((Component)renderer).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.sharedMesh == (Object)null) { return null; } Bounds bounds = component.sharedMesh.bounds; Vector3 size = ((Bounds)(ref bounds)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f) { return null; } BoxCollider val = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val == (Object)null) { val = ((Component)renderer).gameObject.AddComponent(); } val.center = ((Bounds)(ref bounds)).center; val.size = ClampColliderSize(((Bounds)(ref bounds)).size); CopyColliderSettings(templateCollider, (Collider)(object)val); return (Collider)(object)val; } private static Collider AddBoxColliderForSkinnedRenderer(SkinnedMeshRenderer renderer, Collider templateCollider) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return null; } if (HasNegativeScaleInHierarchy(((Component)renderer).transform)) { return null; } Bounds val = ((Renderer)renderer).localBounds; Vector3 size = ((Bounds)(ref val)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f && (Object)(object)renderer.sharedMesh != (Object)null) { val = renderer.sharedMesh.bounds; } size = ((Bounds)(ref val)).size; if (((Vector3)(ref size)).sqrMagnitude <= 0f) { return null; } BoxCollider val2 = ((Component)renderer).gameObject.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)renderer).gameObject.AddComponent(); } val2.center = ((Bounds)(ref val)).center; val2.size = ClampColliderSize(((Bounds)(ref val)).size); CopyColliderSettings(templateCollider, (Collider)(object)val2); return (Collider)(object)val2; } private static void EncapsulateBoundsCorners(ref Bounds aggregateBounds, ref bool hasBounds, Transform root, Bounds rendererBounds) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) Vector3 center = ((Bounds)(ref rendererBounds)).center; Vector3 extents = ((Bounds)(ref rendererBounds)).extents; Vector3[] array = (Vector3[])(object)new Vector3[8] { center + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z), center + new Vector3(0f - extents.x, 0f - extents.y, extents.z), center + new Vector3(0f - extents.x, extents.y, 0f - extents.z), center + new Vector3(0f - extents.x, extents.y, extents.z), center + new Vector3(extents.x, 0f - extents.y, 0f - extents.z), center + new Vector3(extents.x, 0f - extents.y, extents.z), center + new Vector3(extents.x, extents.y, 0f - extents.z), center + new Vector3(extents.x, extents.y, extents.z) }; for (int i = 0; i < array.Length; i++) { Vector3 val = root.InverseTransformPoint(array[i]); if (!hasBounds) { aggregateBounds = new Bounds(val, Vector3.zero); hasBounds = true; } else { ((Bounds)(ref aggregateBounds)).Encapsulate(val); } } } private static Collider AddFallbackRootCollider(Transform mikuRoot, Collider templateCollider) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mikuRoot == (Object)null) { return null; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); Bounds aggregateBounds = default(Bounds); bool hasBounds = false; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { EncapsulateBoundsCorners(ref aggregateBounds, ref hasBounds, mikuRoot, val.bounds); } } if (!hasBounds) { return null; } BoxCollider val2 = ((Component)mikuRoot).gameObject.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)mikuRoot).gameObject.AddComponent(); } val2.center = ((Bounds)(ref aggregateBounds)).center; val2.size = ClampColliderSize(((Bounds)(ref aggregateBounds)).size); CopyColliderSettings(templateCollider, (Collider)(object)val2); return (Collider)(object)val2; } private static void RebuildModelColliders(Item item, Transform mikuRoot) { if ((Object)(object)item == (Object)null || (Object)(object)mikuRoot == (Object)null) { return; } Collider templateCollider = FindColliderTemplate(item); Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } List list = new List(); bool flag = Plugin.RuntimeReplacementModel != null; MeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { Collider val2 = (flag ? AddConvexMeshColliderForMeshRenderer(componentsInChildren2[j], templateCollider) : AddBoxColliderForMeshRenderer(componentsInChildren2[j], templateCollider)); if ((Object)(object)val2 != (Object)null) { list.Add(val2); } } SkinnedMeshRenderer[] componentsInChildren3 = ((Component)mikuRoot).GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren3.Length; k++) { Collider val3 = AddBoxColliderForSkinnedRenderer(componentsInChildren3[k], templateCollider); if ((Object)(object)val3 != (Object)null) { list.Add(val3); } } if (list.Count == 0) { Collider val4 = AddFallbackRootCollider(mikuRoot, templateCollider); if ((Object)(object)val4 != (Object)null) { list.Add(val4); } } if (list.Count > 0) { item.colliders = list.ToArray(); DisableOriginalColliders(item); } } private static void EnsureModelColliders(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { RebuildModelColliders(item, mikuRoot); componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); } if (componentsInChildren.Length != 0) { SetColliderArrayEnabled(componentsInChildren, enabled: true); item.colliders = componentsInChildren; DisableOriginalColliders(item); } } } private static void SetColliderArrayEnabled(Collider[] colliders, bool enabled) { if (colliders == null) { return; } foreach (Collider val in colliders) { if (!((Object)(object)val == (Object)null)) { val.enabled = enabled; } } } private static void SyncCollidersByState(Item item, Transform mikuRoot) { if (!((Object)(object)item == (Object)null) && !((Object)(object)mikuRoot == (Object)null)) { Collider[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); if (IsHeld(item)) { SetColliderArrayEnabled(componentsInChildren, enabled: false); EnableOriginalColliders(item); } else { EnsureModelColliders(item, mikuRoot); } } } private static int DetermineTargetLayer(Item item) { if ((Object)(object)item == (Object)null) { return 0; } Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { return ((Component)val).gameObject.layer; } } return ((Component)item).gameObject.layer; } private static void ConfigureMikuRenderer(Renderer renderer, int targetLayer) { ((Component)renderer).gameObject.layer = targetLayer; renderer.allowOcclusionWhenDynamic = false; renderer.shadowCastingMode = (ShadowCastingMode)1; renderer.receiveShadows = true; renderer.forceRenderingOff = false; renderer.enabled = true; renderer.SetPropertyBlock((MaterialPropertyBlock)null); if (!((Component)renderer).gameObject.activeSelf) { ((Component)renderer).gameObject.SetActive(true); } } private static bool RendererHasMainTexSlot(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { return false; } foreach (Material val in sharedMaterials) { if ((Object)(object)val != (Object)null && val.HasProperty("_MainTex")) { return true; } } return false; } private static Material CreateMainTexCompatMaterial(Texture texture) { //IL_004f: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown Shader val = Shader.Find("Standard") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("W/Peak_Standard"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { name = "Miku_MainTexCompat", color = Color.white, renderQueue = 2000 }; if ((Object)(object)texture != (Object)null) { ApplyMikuTextureSafe(val2, texture); } ApplyRealisticMaterialTuning(val2); return val2; } private static void EnsureRendererMainTexCompatibility(Renderer renderer) { if ((Object)(object)renderer == (Object)null || Plugin.RuntimeReplacementModel != null) { return; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { Material val = CreateMainTexCompatMaterial(GetMikuTexture()) ?? CreateRendererMaterialInstance(); if ((Object)(object)val != (Object)null) { renderer.sharedMaterial = val; } return; } for (int i = 0; i < sharedMaterials.Length; i++) { if ((Object)(object)sharedMaterials[i] != (Object)null && sharedMaterials[i].HasProperty("_MainTex")) { return; } } Material val2 = CreateMainTexCompatMaterial(GetMikuTexture()); if (!((Object)(object)val2 == (Object)null)) { sharedMaterials[0] = val2; renderer.sharedMaterials = sharedMaterials; } } private static Renderer[] BuildAdditionalRenderers(Renderer primaryRenderer, Renderer[] renderers) { if (renderers == null || renderers.Length == 0) { return Array.Empty(); } List list = new List(); foreach (Renderer val in renderers) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)primaryRenderer)) { list.Add(val); } } if (list.Count != 0) { return list.ToArray(); } return Array.Empty(); } private static bool TryGetOriginalItemRenderers(Item item, out Renderer primaryRenderer, out Renderer[] additionalRenderers) { primaryRenderer = null; additionalRenderers = Array.Empty(); if ((Object)(object)item == (Object)null) { return false; } Renderer[] componentsInChildren = ((Component)item).gameObject.GetComponentsInChildren(true); List list = new List(); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !IsMikuTransform(((Component)val).transform)) { list.Add(val); } } if (list.Count == 0) { return false; } for (int j = 0; j < list.Count; j++) { Renderer val2 = list[j]; if ((Object)(object)primaryRenderer == (Object)null) { primaryRenderer = val2; } if (RendererHasMainTexSlot(val2)) { primaryRenderer = val2; break; } } if ((Object)(object)primaryRenderer == (Object)null) { return false; } additionalRenderers = BuildAdditionalRenderers(primaryRenderer, list.ToArray()); return true; } private static void EnsureItemRendererRefs(Item item, Transform mikuRoot) { if (Plugin.KeepOriginalRendererRefs && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers)) { item.mainRenderer = primaryRenderer; item.addtlRenderers = additionalRenderers; return; } Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); if (componentsInChildren.Length == 0) { return; } Renderer val = null; foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { if ((Object)(object)val == (Object)null) { val = val2; } if (RendererHasMainTexSlot(val2)) { val = val2; break; } } } if (!((Object)(object)val == (Object)null)) { EnsureRendererMainTexCompatibility(val); item.mainRenderer = val; item.addtlRenderers = BuildAdditionalRenderers(val, componentsInChildren); } } private static void RestoreOriginalItemRendererRefs(Item item) { if (!((Object)(object)item == (Object)null) && TryGetOriginalItemRenderers(item, out var primaryRenderer, out var additionalRenderers)) { item.mainRenderer = primaryRenderer; item.addtlRenderers = additionalRenderers; } } private static void RemoveReplacement(Item item, Transform mikuRoot) { EnableOriginalRenderers(item); EnableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); if ((Object)(object)mikuRoot != (Object)null) { Object.Destroy((Object)(object)((Component)mikuRoot).gameObject); } } private static void ApplyInitialMikuRendererSetup(Item item, Transform mikuRoot) { int num = DetermineTargetLayer(item); ((Component)mikuRoot).gameObject.layer = num; MeshRenderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); SkinnedMeshRenderer[] componentsInChildren2 = ((Component)mikuRoot).GetComponentsInChildren(true); Plugin.VerboseLog("[ItemPatch] Renderer layout for " + ((Object)item).name + ": MeshRenderers=" + componentsInChildren.Length + ", SkinnedMeshRenderers=" + componentsInChildren2.Length); foreach (MeshRenderer renderer in componentsInChildren) { ConfigureMikuRenderer((Renderer)(object)renderer, num); ApplyMaterialToMeshRenderer(renderer); } foreach (SkinnedMeshRenderer obj in componentsInChildren2) { obj.updateWhenOffscreen = true; ConfigureMikuRenderer((Renderer)(object)obj, num); ApplyMaterialToSkinnedRenderer(obj); } EnsureItemRendererRefs(item, mikuRoot); } private static bool IsWhitelistedBehaviour(MonoBehaviour behaviour) { if (!(behaviour is MikuMarker) && !(behaviour is MikuRendererGuard) && !(behaviour is MikuDeformGuard)) { return behaviour is MikuExpressionController; } return true; } private static void SanitizeVisualObject(GameObject visualRoot, int targetLayer) { Collider[] componentsInChildren = visualRoot.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null)) { val.enabled = false; Object.Destroy((Object)(object)val); } } Rigidbody[] componentsInChildren2 = visualRoot.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if ((Object)(object)componentsInChildren2[j] != (Object)null) { Object.Destroy((Object)(object)componentsInChildren2[j]); } } Joint[] componentsInChildren3 = visualRoot.GetComponentsInChildren(true); for (int k = 0; k < componentsInChildren3.Length; k++) { if ((Object)(object)componentsInChildren3[k] != (Object)null) { Object.Destroy((Object)(object)componentsInChildren3[k]); } } LODGroup[] componentsInChildren4 = visualRoot.GetComponentsInChildren(true); foreach (LODGroup val2 in componentsInChildren4) { if (!((Object)(object)val2 == (Object)null)) { val2.enabled = false; Object.Destroy((Object)(object)val2); } } MonoBehaviour[] componentsInChildren5 = visualRoot.GetComponentsInChildren(true); foreach (MonoBehaviour val3 in componentsInChildren5) { if (!((Object)(object)val3 == (Object)null) && !IsWhitelistedBehaviour(val3)) { ((Behaviour)val3).enabled = false; Object.Destroy((Object)(object)val3); } } Transform[] componentsInChildren6 = visualRoot.GetComponentsInChildren(true); foreach (Transform val4 in componentsInChildren6) { if (!((Object)(object)val4 == (Object)null)) { ((Component)val4).gameObject.tag = "Untagged"; ((Component)val4).gameObject.layer = targetLayer; } } } private static bool ContainsKeyword(string value, string[] keywords) { if (string.IsNullOrEmpty(value)) { return false; } string text = value.ToLowerInvariant(); for (int i = 0; i < keywords.Length; i++) { if (text.Contains(keywords[i])) { return true; } } return false; } private static void RemoveUnwantedFootAttachments(Transform mikuRoot) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = ((Component)mikuRoot).GetComponentsInChildren(true); int num = 0; foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ContainsKeyword(((Object)((Component)val).gameObject).name, UnwantedFootKeywords)) { Bounds bounds = val.bounds; if (!(mikuRoot.InverseTransformPoint(((Bounds)(ref bounds)).center).y > 0.2f)) { Object.Destroy((Object)(object)((Component)val).gameObject); num++; } } } if (num > 0) { Plugin.VerboseLog("[ItemPatch] Removed unwanted foot attachments: " + num); } } private static void SyncVisibilityState(Item item) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) Transform val = FindMikuRoot(item); if ((Object)(object)val == (Object)null) { return; } int num = DetermineTargetLayer(item); ((Component)val).gameObject.layer = num; ResolvePoseByState(item, out var localPosition, out var localRotation, out var localScale); if (val.localPosition != localPosition) { val.localPosition = localPosition; } if (val.localRotation != localRotation) { val.localRotation = localRotation; } if (val.localScale != localScale) { val.localScale = localScale; } MikuDeformGuard component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.SetRootTarget(localPosition, localRotation, localScale); } bool flag = ShouldShowReplacement(item); if (((Component)val).gameObject.activeSelf != flag) { ((Component)val).gameObject.SetActive(flag); } if (!flag) { EnableOriginalRenderers(item); EnableOriginalColliders(item); RestoreOriginalItemRendererRefs(item); return; } SyncCollidersByState(item, val); if (HasVisibleReplacementRenderers(val)) { DisableOriginalRenderers(item); } else { EnableOriginalRenderers(item); } Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { ConfigureMikuRenderer(val2, num); } } EnsureItemRendererRefs(item, val); } private static Transform EnsureMikuModel(Item item, bool createIfMissing) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) Transform val = FindMikuRoot(item); if ((Object)(object)val != (Object)null) { return val; } if (!createIfMissing) { return null; } GameObject val2 = Plugin.CreateReplacementVisualInstance("MikuFumo_Visual"); if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"[ItemPatch] Replacement visual is unavailable, cannot create model yet."); return null; } val2.transform.SetParent(((Component)item).transform, false); ((Object)val2).name = "MikuFumo_Visual"; val2.SetActive(true); int targetLayer = (val2.layer = DetermineTargetLayer(item)); ResolvePoseByState(item, out var localPosition, out var localRotation, out var localScale); val2.transform.localPosition = localPosition; val2.transform.localRotation = localRotation; val2.transform.localScale = localScale; if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } RemoveUnwantedFootAttachments(val2.transform); SanitizeVisualObject(val2, targetLayer); MikuRendererGuard mikuRendererGuard = val2.GetComponent(); if ((Object)(object)mikuRendererGuard == (Object)null) { mikuRendererGuard = val2.AddComponent(); } mikuRendererGuard.Bind(item); MikuDeformGuard mikuDeformGuard = val2.GetComponent(); if ((Object)(object)mikuDeformGuard == (Object)null) { mikuDeformGuard = val2.AddComponent(); } mikuDeformGuard.Bind(item); mikuDeformGuard.Initialize(localPosition, localRotation, localScale); MikuExpressionController mikuExpressionController = FindExpressionController(val2.transform); if ((Object)(object)mikuExpressionController != (Object)null) { mikuExpressionController.Bind(item); } ApplyInitialMikuRendererSetup(item, val2.transform); RebuildModelColliders(item, val2.transform); SyncVisibilityState(item); Plugin.VerboseLog("[ItemPatch] Created Miku replacement model under item: " + ((Object)item).name); return val2.transform; } private static void EnsureReplacementAndVisibility(Item item, bool createIfMissing) { if (!IsBingBong(item)) { return; } Transform val = FindMikuRoot(item); if (!Plugin.ModEnabled) { if ((Object)(object)val != (Object)null) { RemoveReplacement(item, val); } return; } if ((Object)(object)val == (Object)null) { val = EnsureMikuModel(item, createIfMissing); } if (!((Object)(object)val == (Object)null)) { MikuRendererGuard component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.Bind(item); } MikuDeformGuard component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.Bind(item); } MikuExpressionController mikuExpressionController = FindExpressionController(val); if ((Object)(object)mikuExpressionController != (Object)null) { mikuExpressionController.Bind(item); } SyncVisibilityState(item); } } [HarmonyPatch("Start")] [HarmonyPostfix] public static void Item_Start(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); if (IsBingBong(__instance)) { Plugin.VerboseLog("[ItemPatch] Model replacement complete for: " + ((Object)__instance).name); } } [HarmonyPatch("OnEnable")] [HarmonyPostfix] public static void Item_OnEnable(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("SetState")] [HarmonyPrefix] public static void Item_SetState_Prefix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("SetState")] [HarmonyPostfix] public static void Item_SetState_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("Update")] [HarmonyPostfix] public static void Item_Update_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: false); } [HarmonyPatch("RequestPickup")] [HarmonyPrefix] public static void Item_RequestPickup_Prefix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("RequestPickup")] [HarmonyPostfix] public static void Item_RequestPickup_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: true); } [HarmonyPatch("HideRenderers")] [HarmonyPrefix] public static bool Item_HideRenderers_Prefix(Item __instance) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.ModEnabled || !IsBingBong(__instance)) { return true; } Transform val = EnsureMikuModel(__instance, createIfMissing: false); if ((Object)(object)val == (Object)null) { return true; } ResolvePoseByState(__instance, out var localPosition, out var localRotation, out var localScale); val.localPosition = localPosition; val.localRotation = localRotation; val.localScale = localScale; if (!((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } MikuDeformGuard component = ((Component)val).GetComponent(); if ((Object)(object)component != (Object)null) { component.SetRootTarget(localPosition, localRotation, localScale); } SyncCollidersByState(__instance, val); int targetLayer = DetermineTargetLayer(__instance); Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null) { ConfigureMikuRenderer(val2, targetLayer); } } DisableOriginalRenderers(__instance); EnsureItemRendererRefs(__instance, val); return false; } [HarmonyPatch("PutInBackpackRPC")] [HarmonyPostfix] public static void Item_PutInBackpackRPC_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: false); } [HarmonyPatch("ClearDataFromBackpack")] [HarmonyPostfix] public static void Item_ClearDataFromBackpack_Postfix(Item __instance) { EnsureReplacementAndVisibility(__instance, createIfMissing: false); } [HarmonyPatch(typeof(ItemUIData), "GetIcon")] [HarmonyPostfix] public static void Item_GetIcon(ItemUIData __instance, ref Texture2D __result) { if (Plugin.ModEnabled && __instance.itemName == "Bing Bong" && (Object)(object)Plugin.MochiTexture != (Object)null) { __result = Plugin.MochiTexture; } } [HarmonyPatch("GetName")] [HarmonyPostfix] public static void Item_GetName_Postfix(Item __instance, ref string __result) { if (Plugin.ModEnabled && IsBingBong(__instance)) { __result = Plugin.ReplacementDisplayName; } } [HarmonyPatch("GetItemName")] [HarmonyPostfix] public static void Item_GetItemName_Postfix(Item __instance, ref string __result) { if (Plugin.ModEnabled && IsBingBong(__instance)) { __result = Plugin.ReplacementDisplayName; } } } [HarmonyPatch] public static class MikuTintCompatibilityPatch { private delegate void ItemCookingIntMethod(ItemCooking instance, int value); private static readonly FieldRef BackpackRenderersRef = AccessTools.FieldRefAccess("renderers"); private static readonly FieldRef BackpackDefaultTintsRef = AccessTools.FieldRefAccess("defaultTints"); private static readonly FieldRef ItemCookingRenderersRef = AccessTools.FieldRefAccess("renderers"); private static readonly FieldRef ItemCookingDefaultTintsRef = AccessTools.FieldRefAccess("defaultTints"); private static readonly FieldRef ItemCookingSetupRef = AccessTools.FieldRefAccess("setup"); private static readonly FieldRef ItemCookingPreCookedRef = AccessTools.FieldRefAccess("preCooked"); private static readonly FieldRef ItemCookingIgnoreDefaultCookBehaviorRef = AccessTools.FieldRefAccess("ignoreDefaultCookBehavior"); private static readonly FieldRef ItemCookingTimesCookedLocalRef = AccessTools.FieldRefAccess("k__BackingField"); private static readonly ItemCookingIntMethod RunAdditionalCookingBehaviorsDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "RunAdditionalCookingBehaviors", (Type[])null, (Type[])null), (object)null, true); private static readonly ItemCookingIntMethod ChangeStatsCookedDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "ChangeStatsCooked", (Type[])null, (Type[])null), (object)null, true); private static readonly ItemCookingIntMethod CookVisuallyDelegate = AccessTools.MethodDelegate(AccessTools.Method(typeof(ItemCooking), "CookVisually", (Type[])null, (Type[])null), (object)null, true); private static Color GetSafeTint(Material material) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material == (Object)null) { return Color.white; } if (material.HasProperty("_Tint")) { return material.GetColor("_Tint"); } if (material.HasProperty("_BaseColor")) { return material.GetColor("_BaseColor"); } if (material.HasProperty("_Color")) { return material.GetColor("_Color"); } return Color.white; } private static void TryApplyTint(Material material, Color color) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material != (Object)null && material.HasProperty("_Tint")) { material.SetColor("_Tint", color); } } private static Color[] CaptureDefaultTints(Renderer[] renderers) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) Color[] array = (Color[])(object)new Color[renderers.Length]; for (int i = 0; i < renderers.Length; i++) { Renderer val = renderers[i]; array[i] = (((Object)(object)val == (Object)null) ? Color.white : GetSafeTint(val.material)); } return array; } private static MeshRenderer[] GetBackpackSafeRenderers(BackpackOnBackVisuals instance) { MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren(); List list = new List(); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val).transform)) { list.Add(val); } } return list.ToArray(); } private static Renderer[] GetItemCookingSafeRenderers(ItemCooking instance) { List list = new List(); MeshRenderer[] componentsInChildren = ((Component)instance).GetComponentsInChildren(); SkinnedMeshRenderer[] componentsInChildren2 = ((Component)instance).GetComponentsInChildren(true); foreach (MeshRenderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val).transform)) { list.Add((Renderer)(object)val); } } foreach (SkinnedMeshRenderer val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null) && !ItemPatch.IsMikuTransform(((Component)val2).transform)) { list.Add((Renderer)(object)val2); } } return list.ToArray(); } private static void EnsureBackpackRendererCache(BackpackOnBackVisuals instance) { MeshRenderer[] array = BackpackRenderersRef.Invoke(instance); Color[] array2 = BackpackDefaultTintsRef.Invoke(instance); bool flag = array == null || array2 == null || array2.Length != array.Length; if (!flag && array.Length != 0) { for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && ItemPatch.IsMikuTransform(((Component)array[i]).transform)) { flag = true; break; } } } if (flag) { array = GetBackpackSafeRenderers(instance); BackpackRenderersRef.Invoke(instance) = array; ref Color[] reference = ref BackpackDefaultTintsRef.Invoke(instance); Renderer[] renderers = (Renderer[])(object)array; reference = CaptureDefaultTints(renderers); } } private static void EnsureItemCookingRendererCache(ItemCooking instance) { Renderer[] array = ItemCookingRenderersRef.Invoke(instance); Color[] array2 = ItemCookingDefaultTintsRef.Invoke(instance); bool flag = !ItemCookingSetupRef.Invoke(instance) || array == null || array2 == null || array2.Length != array.Length; if (!flag && array.Length != 0) { for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && ItemPatch.IsMikuTransform(((Component)array[i]).transform)) { flag = true; break; } } } if (flag) { array = GetItemCookingSafeRenderers(instance); ItemCookingRenderersRef.Invoke(instance) = array; ItemCookingDefaultTintsRef.Invoke(instance) = CaptureDefaultTints(array); ItemCookingSetupRef.Invoke(instance) = true; } } [HarmonyPatch(typeof(BackpackOnBackVisuals), "InitRenderers")] [HarmonyPrefix] public static bool BackpackOnBackVisuals_InitRenderers_Prefix(BackpackOnBackVisuals __instance) { MeshRenderer[] backpackSafeRenderers = GetBackpackSafeRenderers(__instance); BackpackRenderersRef.Invoke(__instance) = backpackSafeRenderers; ref Color[] reference = ref BackpackDefaultTintsRef.Invoke(__instance); Renderer[] renderers = (Renderer[])(object)backpackSafeRenderers; reference = CaptureDefaultTints(renderers); return false; } [HarmonyPatch(typeof(BackpackOnBackVisuals), "CookVisually")] [HarmonyPrefix] public static bool BackpackOnBackVisuals_CookVisually_Prefix(BackpackOnBackVisuals __instance, int __0) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0072: Unknown result type (might be due to invalid IL or missing references) EnsureBackpackRendererCache(__instance); if (__0 <= 0) { return false; } MeshRenderer[] array = BackpackRenderersRef.Invoke(__instance) ?? Array.Empty(); Color[] array2 = BackpackDefaultTintsRef.Invoke(__instance) ?? Array.Empty(); Color cookColor = ItemCooking.GetCookColor(__0); for (int i = 0; i < array.Length; i++) { MeshRenderer val = array[i]; if (!((Object)(object)val == (Object)null)) { Color val2 = ((i < array2.Length) ? array2[i] : Color.white); TryApplyTint(((Renderer)val).material, val2 * cookColor); } } return false; } [HarmonyPatch(typeof(ItemCooking), "UpdateCookedBehavior")] [HarmonyPrefix] public static bool ItemCooking_UpdateCookedBehavior_Prefix(ItemCooking __instance) { Item component = ((Component)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } IntItemData data = component.GetData((DataEntryKey)1); if (data == null) { return true; } if (data.Value == 0) { data.Value += ItemCookingPreCookedRef.Invoke(__instance); } EnsureItemCookingRendererCache(__instance); int num = data.Value - ItemCookingTimesCookedLocalRef.Invoke(__instance); CookVisuallyDelegate(__instance, data.Value); if (!ItemCookingIgnoreDefaultCookBehaviorRef.Invoke(__instance) && num > 0) { for (int i = 1 + ItemCookingTimesCookedLocalRef.Invoke(__instance); i <= data.Value; i++) { ChangeStatsCookedDelegate(__instance, i); } } RunAdditionalCookingBehaviorsDelegate(__instance, data.Value); ItemCookingTimesCookedLocalRef.Invoke(__instance) = data.Value; return false; } [HarmonyPatch(typeof(ItemCooking), "CookVisually")] [HarmonyPrefix] public static bool ItemCooking_CookVisually_Prefix(ItemCooking __instance, int __0) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) EnsureItemCookingRendererCache(__instance); if (__0 <= 0) { return false; } Renderer[] array = ItemCookingRenderersRef.Invoke(__instance) ?? Array.Empty(); Color[] array2 = ItemCookingDefaultTintsRef.Invoke(__instance) ?? Array.Empty(); Color cookColor = ItemCooking.GetCookColor(__0); for (int i = 0; i < array.Length; i++) { Renderer val = array[i]; if (!((Object)(object)val == (Object)null)) { Material[] materials = val.materials; Color color = ((i < array2.Length) ? array2[i] : Color.white) * cookColor; for (int j = 0; j < materials.Length; j++) { TryApplyTint(materials[j], color); } } } return false; } } internal sealed class RuntimeReplacementModel { internal string DisplayName { get; private set; } internal Mesh Mesh { get; private set; } internal Material[] Materials { get; private set; } internal RuntimeBoneInfo[] Bones { get; private set; } internal int RootBoneIndex { get; private set; } internal Vector3 MeshLocalOffset { get; private set; } internal Vector3 RecommendedBaseScale { get; private set; } internal Texture2D PrimaryTexture { get; private set; } internal Texture2D IconTexture { get; private set; } internal bool HasSkinning { get { if ((Object)(object)Mesh != (Object)null && Bones != null && Bones.Length != 0 && Mesh.bindposes != null && Mesh.bindposes.Length == Bones.Length && Mesh.boneWeights != null) { return Mesh.boneWeights.Length == Mesh.vertexCount; } return false; } } internal Material PrimaryMaterial { get { if (Materials == null || Materials.Length == 0) { return null; } return Materials[0]; } } internal RuntimeReplacementModel(string displayName, Mesh mesh, Material[] materials, RuntimeBoneInfo[] bones, int rootBoneIndex, Vector3 meshLocalOffset, Vector3 recommendedBaseScale, Texture2D primaryTexture, Texture2D iconTexture) { //IL_004d: 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) DisplayName = (string.IsNullOrEmpty(displayName) ? "Fufu" : displayName); Mesh = mesh; Materials = materials ?? Array.Empty(); Bones = bones ?? Array.Empty(); RootBoneIndex = rootBoneIndex; MeshLocalOffset = meshLocalOffset; RecommendedBaseScale = recommendedBaseScale; PrimaryTexture = primaryTexture; IconTexture = iconTexture; } internal GameObject Instantiate(string rootName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_002c: 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_0043: 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_0054: 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_0064: 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_0074: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(string.IsNullOrEmpty(rootName) ? "Fufu_Visual" : rootName); if (HasSkinning) { InstantiateSkinned(val); return val; } GameObject val2 = new GameObject("RuntimeMesh"); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = MeshLocalOffset; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; val2.AddComponent().sharedMesh = Mesh; ((Renderer)val2.AddComponent()).sharedMaterials = CloneMaterials(); return val; } private void InstantiateSkinned(GameObject root) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: 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_00ed: 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_0100: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Skeleton"); val.transform.SetParent(root.transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one; Transform[] array = BuildBoneHierarchy(val.transform); GameObject val2 = new GameObject("RuntimeSkinnedMesh"); val2.transform.SetParent(root.transform, false); val2.transform.localPosition = MeshLocalOffset; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = Vector3.one; SkinnedMeshRenderer val3 = val2.AddComponent(); val3.sharedMesh = Mesh; ((Renderer)val3).sharedMaterials = CloneMaterials(); val3.bones = array; val3.rootBone = ResolveRootBone(array, val.transform); val3.updateWhenOffscreen = true; Bounds bounds = Mesh.bounds; ((Bounds)(ref bounds)).Expand(0.5f); ((Renderer)val3).localBounds = bounds; val2.AddComponent().Initialize(val3); } private Transform[] BuildBoneHierarchy(Transform skeletonRoot) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) Transform[] array = (Transform[])(object)new Transform[Bones.Length]; for (int i = 0; i < Bones.Length; i++) { RuntimeBoneInfo runtimeBoneInfo = Bones[i]; GameObject val = new GameObject(string.IsNullOrEmpty(runtimeBoneInfo.Name) ? ("Bone_" + i) : runtimeBoneInfo.Name); array[i] = val.transform; } for (int j = 0; j < Bones.Length; j++) { RuntimeBoneInfo runtimeBoneInfo2 = Bones[j]; if (runtimeBoneInfo2.ParentIndex >= 0 && runtimeBoneInfo2.ParentIndex < array.Length) { array[j].SetParent(array[runtimeBoneInfo2.ParentIndex], false); } else { array[j].SetParent(skeletonRoot, false); } array[j].localPosition = runtimeBoneInfo2.LocalPosition; array[j].localRotation = Quaternion.identity; array[j].localScale = Vector3.one; } return array; } private Transform ResolveRootBone(Transform[] boneTransforms, Transform skeletonRoot) { if (RootBoneIndex >= 0 && RootBoneIndex < boneTransforms.Length) { return boneTransforms[RootBoneIndex]; } return skeletonRoot; } private Material[] CloneMaterials() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (Materials == null || Materials.Length == 0) { return Array.Empty(); } Material[] array = (Material[])(object)new Material[Materials.Length]; for (int i = 0; i < Materials.Length; i++) { Material val = Materials[i]; object obj = array; int num = i; obj = (object)(((Object)(object)val != (Object)null) ? new Material(val) : ((Material)null)); ((object[])obj)[num] = obj; } return array; } } internal sealed class RuntimeBoneInfo { internal string Name; internal int ParentIndex; internal Vector3 AbsolutePosition; internal Vector3 LocalPosition; } internal sealed class MikuExpressionController : MonoBehaviour { private static readonly string[] HeldExpressionCandidates = new string[8] { "笑い", "ウィンク", "ウィンク右", "まばたき", "口角上げ", "あ", "え", "お" }; private SkinnedMeshRenderer _renderer; private readonly Dictionary _blendShapeIndices = new Dictionary(StringComparer.OrdinalIgnoreCase); private Item _boundItem; private string _lastExpressionName = string.Empty; private float _lastExpressionWeight = -1f; private bool _initializedState; private bool _wasHeld; private string _transientExpressionName = string.Empty; private float _transientExpressionUntil; internal void Initialize(SkinnedMeshRenderer renderer) { _renderer = renderer; _blendShapeIndices.Clear(); Mesh val = (((Object)(object)_renderer != (Object)null) ? _renderer.sharedMesh : null); if ((Object)(object)val == (Object)null) { ((Behaviour)this).enabled = false; return; } for (int i = 0; i < val.blendShapeCount; i++) { string blendShapeName = val.GetBlendShapeName(i); if (!string.IsNullOrEmpty(blendShapeName) && !_blendShapeIndices.ContainsKey(blendShapeName)) { _blendShapeIndices.Add(blendShapeName, i); } } if (_blendShapeIndices.Count == 0) { ((Behaviour)this).enabled = false; } } internal void Bind(Item item) { _boundItem = item; } private void LateUpdate() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 if ((Object)(object)_renderer == (Object)null || _blendShapeIndices.Count == 0) { return; } bool flag = (Object)(object)_boundItem != (Object)null && (int)_boundItem.itemState == 1; bool isUsing = flag && (_boundItem.isUsingPrimary || _boundItem.isUsingSecondary); if (!_initializedState) { _initializedState = true; _wasHeld = flag; if (flag) { TriggerHeldExpression(); } } else if (flag && !_wasHeld) { TriggerHeldExpression(); } _wasHeld = flag; string text = ResolveCurrentExpressionName(flag, isUsing); float num = (string.Equals(text, "None", StringComparison.OrdinalIgnoreCase) ? 0f : (Plugin.ExpressionWeight * 100f)); if (string.Equals(text, _lastExpressionName, StringComparison.OrdinalIgnoreCase) && Mathf.Abs(num - _lastExpressionWeight) <= 0.001f) { return; } Mesh sharedMesh = _renderer.sharedMesh; if (!((Object)(object)sharedMesh == (Object)null)) { for (int i = 0; i < sharedMesh.blendShapeCount; i++) { _renderer.SetBlendShapeWeight(i, 0f); } if (!string.Equals(text, "None", StringComparison.OrdinalIgnoreCase) && _blendShapeIndices.TryGetValue(text, out var value)) { _renderer.SetBlendShapeWeight(value, num); } _lastExpressionName = text; _lastExpressionWeight = num; } } private string ResolveCurrentExpressionName(bool isHeld, bool isUsing) { if (isUsing && HasBlendShape("はぅ")) { return "はぅ"; } if (isHeld && !string.IsNullOrEmpty(_transientExpressionName) && Time.time < _transientExpressionUntil && HasBlendShape(_transientExpressionName)) { return _transientExpressionName; } string expressionName = Plugin.ExpressionName; if (!HasBlendShape(expressionName)) { return "None"; } return expressionName; } private void TriggerHeldExpression() { _transientExpressionName = PickHeldExpression(); _transientExpressionUntil = Time.time + Random.Range(2f, 3f); } private string PickHeldExpression() { string expressionName = Plugin.ExpressionName; string[] array = (string[])HeldExpressionCandidates.Clone(); for (int i = 0; i < array.Length; i++) { int num = Random.Range(i, array.Length); string text = array[i]; array[i] = array[num]; array[num] = text; } foreach (string text2 in array) { if (!string.Equals(text2, expressionName, StringComparison.OrdinalIgnoreCase) && HasBlendShape(text2)) { return text2; } } return "None"; } private bool HasBlendShape(string expressionName) { if (!string.IsNullOrEmpty(expressionName) && !string.Equals(expressionName, "None", StringComparison.OrdinalIgnoreCase)) { return _blendShapeIndices.ContainsKey(expressionName); } return false; } } internal static class RuntimePmxLoader { private sealed class PmxMaterialInfo { internal string Name; internal string MainTexturePath; internal string ToonTexturePath; internal Color DiffuseColor; internal int SurfaceIndexCount; } private struct PmxVertexWeight { internal int BoneIndex0; internal int BoneIndex1; internal int BoneIndex2; internal int BoneIndex3; internal float Weight0; internal float Weight1; internal float Weight2; internal float Weight3; } private sealed class PmxMorphInfo { internal string Name; internal Dictionary VertexOffsets = new Dictionary(); } private sealed class PmxHeader { internal Encoding TextEncoding; internal int AdditionalUvCount; internal int VertexIndexSize; internal int TextureIndexSize; internal int MaterialIndexSize; internal int BoneIndexSize; internal int MorphIndexSize; } private const string PreferredModelFileName = "fufummd1.pmx"; private static readonly Vector3 ReferenceVisibleSizeAtBaseScale = new Vector3(1.5852638f, 1.2168914f, 0.8999324f); private static readonly Vector3 ReferenceVisibleCenterAtBaseScale = new Vector3(0.0330699f, 0.06277876f, 0.09902591f); internal static RuntimeReplacementModel Load(string replacementRoot, ManualLogSource log) { try { if (string.IsNullOrEmpty(replacementRoot) || !Directory.Exists(replacementRoot)) { return null; } string text = FindPmxPath(replacementRoot); if (string.IsNullOrEmpty(text)) { return null; } return BuildRuntimeModel(text, log); } catch (Exception ex) { if (log != null) { log.LogError((object)("Failed to load runtime PMX replacement: " + ex)); } return null; } } private static string FindPmxPath(string replacementRoot) { string text = Path.Combine(replacementRoot, "fufummd1.pmx"); if (File.Exists(text)) { return text; } string[] files = Directory.GetFiles(replacementRoot, "*.pmx", SearchOption.TopDirectoryOnly); if (files.Length == 0) { return null; } return files[0]; } private static RuntimeReplacementModel BuildRuntimeModel(string pmxPath, ManualLogSource log) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) using FileStream input = File.OpenRead(pmxPath); using BinaryReader binaryReader = new BinaryReader(input); PmxHeader pmxHeader = ReadHeader(binaryReader); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); ReadText(binaryReader, pmxHeader.TextEncoding); int num = binaryReader.ReadInt32(); Vector3[] array = (Vector3[])(object)new Vector3[num]; Vector3[] array2 = (Vector3[])(object)new Vector3[num]; Vector2[] array3 = (Vector2[])(object)new Vector2[num]; PmxVertexWeight[] array4 = new PmxVertexWeight[num]; for (int i = 0; i < num; i++) { array[i] = ConvertPosition(ReadVector3(binaryReader)); array2[i] = ConvertNormal(ReadVector3(binaryReader)); array3[i] = ConvertUv(ReadVector2(binaryReader)); SkipAdditionalUv(binaryReader, pmxHeader.AdditionalUvCount); array4[i] = ReadVertexWeight(binaryReader, pmxHeader.BoneIndexSize); binaryReader.ReadSingle(); } int num2 = binaryReader.ReadInt32(); int[] array5 = new int[num2]; for (int j = 0; j < num2; j++) { array5[j] = ReadUnsignedIndex(binaryReader, pmxHeader.VertexIndexSize); } List texturePaths = ReadTexturePaths(binaryReader, pmxHeader.TextEncoding, pmxPath); List materials = ReadMaterials(binaryReader, pmxHeader, texturePaths); Dictionary textureCache = new Dictionary(StringComparer.OrdinalIgnoreCase); Texture2D primaryTexture; Texture2D iconTexture; Material[] array6 = BuildMaterials(materials, textureCache, log, out primaryTexture, out iconTexture); Mesh val = BuildMesh(Path.GetFileNameWithoutExtension(pmxPath), array, array2, array3, array5, materials); RuntimeBoneInfo[] array7 = ReadBones(binaryReader, pmxHeader); List morphs = ReadMorphs(binaryReader, pmxHeader); SkipDisplayFrames(binaryReader, pmxHeader); Bounds bounds = val.bounds; Vector3 recommendedBaseScale = CalculateRecommendedBaseScale(((Bounds)(ref bounds)).size.y); Vector3 meshLocalOffset = CalculateMeshOffset(val.bounds, recommendedBaseScale); int num3 = DetermineRootBoneIndex(array7); bool flag = TryApplySkinning(val, array7, array4, meshLocalOffset, num3, log); int num4 = ApplyExpressionBlendShapes(val, morphs, log); if (log != null) { string[] obj = new string[14] { "[RuntimePmxLoader] PMX mesh ready: subMeshes=", val.subMeshCount.ToString(), ", materials=", array6.Length.ToString(), ", bones=", array7.Length.ToString(), ", skinned=", flag.ToString(), ", expressionShapes=", num4.ToString(), ", boundsSize=", null, null, null }; bounds = val.bounds; Vector3 size = ((Bounds)(ref bounds)).size; obj[11] = ((Vector3)(ref size)).ToString("F4"); obj[12] = ", baseScale="; obj[13] = ((Vector3)(ref recommendedBaseScale)).ToString("F4"); log.LogInfo((object)string.Concat(obj)); } return new RuntimeReplacementModel("Fufu", val, array6, flag ? array7 : Array.Empty(), flag ? num3 : (-1), meshLocalOffset, recommendedBaseScale, primaryTexture, iconTexture); } private static PmxHeader ReadHeader(BinaryReader reader) { string @string = Encoding.ASCII.GetString(reader.ReadBytes(4)); if (!string.Equals(@string, "PMX ", StringComparison.Ordinal)) { throw new InvalidDataException("Unsupported PMX signature: " + @string); } float num = reader.ReadSingle(); if (num < 2f || num >= 3f) { throw new InvalidDataException("Unsupported PMX version: " + num); } byte count = reader.ReadByte(); byte[] array = reader.ReadBytes(count); if (array.Length < 8) { throw new InvalidDataException("PMX header is incomplete."); } return new PmxHeader { TextEncoding = ((array[0] == 0) ? Encoding.Unicode : Encoding.UTF8), AdditionalUvCount = array[1], VertexIndexSize = array[2], TextureIndexSize = array[3], MaterialIndexSize = array[4], BoneIndexSize = array[5], MorphIndexSize = array[6] }; } private static string ReadText(BinaryReader reader, Encoding encoding) { int num = reader.ReadInt32(); if (num <= 0) { return string.Empty; } byte[] bytes = reader.ReadBytes(num); return encoding.GetString(bytes); } private static void SkipAdditionalUv(BinaryReader reader, int additionalUvCount) { for (int i = 0; i < additionalUvCount; i++) { reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); } } private static PmxVertexWeight ReadVertexWeight(BinaryReader reader, int boneIndexSize) { PmxVertexWeight result = default(PmxVertexWeight); byte b = reader.ReadByte(); switch (b) { case 0: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = 1f; break; case 1: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = 1f - result.Weight0; break; case 2: case 4: result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex2 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex3 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = reader.ReadSingle(); result.Weight2 = reader.ReadSingle(); result.Weight3 = reader.ReadSingle(); break; case 3: { result.BoneIndex0 = ReadSignedIndex(reader, boneIndexSize); result.BoneIndex1 = ReadSignedIndex(reader, boneIndexSize); result.Weight0 = reader.ReadSingle(); result.Weight1 = 1f - result.Weight0; for (int i = 0; i < 9; i++) { reader.ReadSingle(); } break; } default: throw new InvalidDataException("Unsupported PMX vertex deform type: " + b); } return result; } private static List ReadTexturePaths(BinaryReader reader, Encoding encoding, string pmxPath) { int num = reader.ReadInt32(); List list = new List(num); string baseDirectory = Path.GetDirectoryName(pmxPath) ?? string.Empty; for (int i = 0; i < num; i++) { string relativePath = ReadText(reader, encoding); list.Add(ResolveRelativePath(baseDirectory, relativePath)); } return list; } private static List ReadMaterials(BinaryReader reader, PmxHeader header, List texturePaths) { //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) int num = reader.ReadInt32(); List list = new List(num); Color diffuseColor = default(Color); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); ((Color)(ref diffuseColor))..ctor(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadByte(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); int index = ReadSignedIndex(reader, header.TextureIndexSize); ReadSignedIndex(reader, header.TextureIndexSize); reader.ReadByte(); byte b = reader.ReadByte(); int index2 = ((b == 0) ? ReadSignedIndex(reader, header.TextureIndexSize) : reader.ReadByte()); ReadText(reader, header.TextEncoding); int surfaceIndexCount = reader.ReadInt32(); list.Add(new PmxMaterialInfo { Name = name, MainTexturePath = GetTexturePath(texturePaths, index), ToonTexturePath = ((b == 0) ? GetTexturePath(texturePaths, index2) : null), DiffuseColor = diffuseColor, SurfaceIndexCount = surfaceIndexCount }); _ = 0; } return list; } private static RuntimeBoneInfo[] ReadBones(BinaryReader reader, PmxHeader header) { //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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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) int num = reader.ReadInt32(); RuntimeBoneInfo[] array = new RuntimeBoneInfo[num]; for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); Vector3 val = ConvertPosition(ReadVector3(reader)); int parentIndex = ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadInt32(); ushort num2 = reader.ReadUInt16(); if (((uint)num2 & (true ? 1u : 0u)) != 0) { ReadSignedIndex(reader, header.BoneIndexSize); } else { ConvertPosition(ReadVector3(reader)); } if ((num2 & 0x100u) != 0) { ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadSingle(); } if ((num2 & 0x200u) != 0) { ReadSignedIndex(reader, header.BoneIndexSize); reader.ReadSingle(); } if ((num2 & 0x400u) != 0) { ReadVector3(reader); } if ((num2 & 0x800u) != 0) { ReadVector3(reader); ReadVector3(reader); } if ((num2 & 0x2000u) != 0) { reader.ReadInt32(); } if ((num2 & 0x20u) != 0) { SkipIkData(reader, header.BoneIndexSize); } array[i] = new RuntimeBoneInfo { Name = name, ParentIndex = parentIndex, AbsolutePosition = val, LocalPosition = val }; } foreach (RuntimeBoneInfo runtimeBoneInfo in array) { if (runtimeBoneInfo.ParentIndex >= 0 && runtimeBoneInfo.ParentIndex < array.Length) { runtimeBoneInfo.LocalPosition = runtimeBoneInfo.AbsolutePosition - array[runtimeBoneInfo.ParentIndex].AbsolutePosition; } else { runtimeBoneInfo.LocalPosition = runtimeBoneInfo.AbsolutePosition; } } return array; } private static void SkipIkData(BinaryReader reader, int boneIndexSize) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) ReadSignedIndex(reader, boneIndexSize); reader.ReadInt32(); reader.ReadSingle(); int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ReadSignedIndex(reader, boneIndexSize); if (reader.ReadByte() != 0) { ReadVector3(reader); ReadVector3(reader); } } } private static List ReadMorphs(BinaryReader reader, PmxHeader header) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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) int num = reader.ReadInt32(); List list = new List(num); for (int i = 0; i < num; i++) { string name = ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); reader.ReadByte(); byte b = reader.ReadByte(); int num2 = reader.ReadInt32(); if (b == 1) { PmxMorphInfo pmxMorphInfo = new PmxMorphInfo { Name = name }; for (int j = 0; j < num2; j++) { int key = ReadUnsignedIndex(reader, header.VertexIndexSize); Vector3 value = ConvertPosition(ReadVector3(reader)); pmxMorphInfo.VertexOffsets[key] = value; } list.Add(pmxMorphInfo); } else { SkipMorphOffsets(reader, header, b, num2); } } return list; } private static void SkipDisplayFrames(BinaryReader reader, PmxHeader header) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ReadText(reader, header.TextEncoding); ReadText(reader, header.TextEncoding); reader.ReadByte(); int num2 = reader.ReadInt32(); for (int j = 0; j < num2; j++) { if (reader.ReadByte() == 0) { ReadSignedIndex(reader, header.BoneIndexSize); } else { ReadSignedIndex(reader, header.MorphIndexSize); } } } } private static void SkipMorphOffsets(BinaryReader reader, PmxHeader header, byte morphType, int offsetCount) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < offsetCount; i++) { switch (morphType) { case 0: ReadSignedIndex(reader, header.MorphIndexSize); reader.ReadSingle(); break; case 2: ReadSignedIndex(reader, header.BoneIndexSize); ReadVector3(reader); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); break; case 3: case 4: case 5: case 6: case 7: ReadUnsignedIndex(reader, header.VertexIndexSize); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); reader.ReadSingle(); break; case 8: { ReadSignedIndex(reader, header.MaterialIndexSize); reader.ReadByte(); for (int j = 0; j < 28; j++) { reader.ReadSingle(); } break; } default: throw new InvalidDataException("Unsupported PMX morph type: " + morphType); } } } private static int ApplyExpressionBlendShapes(Mesh mesh, List morphs, ManualLogSource log) { //IL_009c: 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) if ((Object)(object)mesh == (Object)null || morphs == null || morphs.Count == 0) { return 0; } int vertexCount = mesh.vertexCount; int num = 0; Vector3[] array = (Vector3[])(object)new Vector3[vertexCount]; for (int i = 0; i < morphs.Count; i++) { PmxMorphInfo pmxMorphInfo = morphs[i]; if (pmxMorphInfo == null || pmxMorphInfo.VertexOffsets.Count == 0 || !IsSupportedExpressionMorphName(pmxMorphInfo.Name)) { continue; } Vector3[] array2 = (Vector3[])(object)new Vector3[vertexCount]; foreach (KeyValuePair vertexOffset in pmxMorphInfo.VertexOffsets) { if (vertexOffset.Key >= 0 && vertexOffset.Key < vertexCount) { array2[vertexOffset.Key] = vertexOffset.Value; } } mesh.AddBlendShapeFrame(pmxMorphInfo.Name, 100f, array2, array, array); num++; } if (num > 0 && log != null) { log.LogInfo((object)("[RuntimePmxLoader] Added expression blend shapes: " + num)); } return num; } private static bool IsSupportedExpressionMorphName(string morphName) { if (!string.IsNullOrEmpty(morphName)) { if (!string.Equals(morphName, "まばたき", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "blink", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "笑い", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク右", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク2", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "ウィンク2右", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "あ", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "い", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "う", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "え", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "お", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "あ2", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "口角上げ", StringComparison.OrdinalIgnoreCase) && !string.Equals(morphName, "口角下げ", StringComparison.OrdinalIgnoreCase)) { return string.Equals(morphName, "はぅ", StringComparison.OrdinalIgnoreCase); } return true; } return false; } private static int DetermineRootBoneIndex(RuntimeBoneInfo[] bones) { if (bones == null || bones.Length == 0) { return -1; } for (int i = 0; i < bones.Length; i++) { string text = bones[i].Name ?? string.Empty; if (text.IndexOf("全て", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("root", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("center", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("センター", StringComparison.OrdinalIgnoreCase) >= 0) { return i; } } for (int j = 0; j < bones.Length; j++) { if (bones[j].ParentIndex < 0) { return j; } } return 0; } private static bool TryApplySkinning(Mesh mesh, RuntimeBoneInfo[] bones, PmxVertexWeight[] vertexWeights, Vector3 meshLocalOffset, int rootBoneIndex, ManualLogSource log) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mesh == (Object)null || bones == null || bones.Length == 0 || vertexWeights == null || vertexWeights.Length != mesh.vertexCount) { return false; } try { mesh.boneWeights = BuildBoneWeights(vertexWeights, bones.Length, rootBoneIndex); mesh.bindposes = BuildBindPoses(bones, meshLocalOffset); return true; } catch (Exception ex) { if (log != null) { log.LogWarning((object)("[RuntimePmxLoader] Failed to apply PMX skinning, fallback to static mesh: " + ex.Message)); } return false; } } private static BoneWeight[] BuildBoneWeights(PmxVertexWeight[] sourceWeights, int boneCount, int fallbackBoneIndex) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[sourceWeights.Length]; int num = Mathf.Clamp(fallbackBoneIndex, 0, Mathf.Max(0, boneCount - 1)); for (int i = 0; i < sourceWeights.Length; i++) { PmxVertexWeight pmxVertexWeight = sourceWeights[i]; BoneWeight val = default(BoneWeight); ((BoneWeight)(ref val)).boneIndex0 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex0, boneCount, num); ((BoneWeight)(ref val)).boneIndex1 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex1, boneCount, num); ((BoneWeight)(ref val)).boneIndex2 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex2, boneCount, num); ((BoneWeight)(ref val)).boneIndex3 = SanitizeBoneIndex(pmxVertexWeight.BoneIndex3, boneCount, num); ((BoneWeight)(ref val)).weight0 = Mathf.Max(0f, pmxVertexWeight.Weight0); ((BoneWeight)(ref val)).weight1 = Mathf.Max(0f, pmxVertexWeight.Weight1); ((BoneWeight)(ref val)).weight2 = Mathf.Max(0f, pmxVertexWeight.Weight2); ((BoneWeight)(ref val)).weight3 = Mathf.Max(0f, pmxVertexWeight.Weight3); BoneWeight val2 = val; float num2 = ((BoneWeight)(ref val2)).weight0 + ((BoneWeight)(ref val2)).weight1 + ((BoneWeight)(ref val2)).weight2 + ((BoneWeight)(ref val2)).weight3; if (num2 <= 0.0001f) { ((BoneWeight)(ref val2)).boneIndex0 = num; ((BoneWeight)(ref val2)).weight0 = 1f; ((BoneWeight)(ref val2)).weight1 = 0f; ((BoneWeight)(ref val2)).weight2 = 0f; ((BoneWeight)(ref val2)).weight3 = 0f; } else { float num3 = 1f / num2; ((BoneWeight)(ref val2)).weight0 = ((BoneWeight)(ref val2)).weight0 * num3; ((BoneWeight)(ref val2)).weight1 = ((BoneWeight)(ref val2)).weight1 * num3; ((BoneWeight)(ref val2)).weight2 = ((BoneWeight)(ref val2)).weight2 * num3; ((BoneWeight)(ref val2)).weight3 = ((BoneWeight)(ref val2)).weight3 * num3; } array[i] = val2; } return array; } private static int SanitizeBoneIndex(int boneIndex, int boneCount, int fallbackBoneIndex) { if (boneIndex < 0 || boneIndex >= boneCount) { return fallbackBoneIndex; } return boneIndex; } private static Matrix4x4[] BuildBindPoses(RuntimeBoneInfo[] bones, Vector3 meshLocalOffset) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0022: Unknown result type (might be due to invalid IL or missing references) Matrix4x4[] array = (Matrix4x4[])(object)new Matrix4x4[bones.Length]; for (int i = 0; i < bones.Length; i++) { array[i] = Matrix4x4.Translate(meshLocalOffset - bones[i].AbsolutePosition); } return array; } private static Material[] BuildMaterials(List materials, Dictionary textureCache, ManualLogSource log, out Texture2D primaryTexture, out Texture2D iconTexture) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0135: 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) primaryTexture = null; iconTexture = null; Shader val = FindCompatibleShader(); Material[] array = (Material[])(object)new Material[Mathf.Max(1, materials.Count)]; for (int i = 0; i < array.Length; i++) { PmxMaterialInfo pmxMaterialInfo = ((i < materials.Count) ? materials[i] : null); Material val2 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(Shader.Find("Standard"))); ((Object)val2).name = ((pmxMaterialInfo != null && !string.IsNullOrEmpty(pmxMaterialInfo.Name)) ? pmxMaterialInfo.Name : ("FufuMaterial_" + i)); val2.renderQueue = 2000; Texture2D val3 = LoadTexture(pmxMaterialInfo?.MainTexturePath, textureCache, log); if ((Object)(object)val3 == (Object)null && pmxMaterialInfo != null && IsFaceMaterial(pmxMaterialInfo.Name)) { val3 = LoadNamedTexture(textureCache, pmxMaterialInfo, "face", log); } if ((Object)(object)val3 != (Object)null && (Object)(object)primaryTexture == (Object)null) { primaryTexture = val3; } if ((Object)(object)val3 != (Object)null && (Object)(object)iconTexture == (Object)null && IsIconMaterial((pmxMaterialInfo != null) ? pmxMaterialInfo.Name : string.Empty)) { iconTexture = val3; } ApplyTexture(val2, val3); ApplyColor(val2, pmxMaterialInfo?.DiffuseColor ?? Color.white); ConfigureOpaqueSurface(val2); array[i] = val2; } if ((Object)(object)primaryTexture == (Object)null) { primaryTexture = FindFirstTexture(textureCache); } if ((Object)(object)iconTexture == (Object)null) { iconTexture = primaryTexture; } return array; } private static Texture2D FindFirstTexture(Dictionary textureCache) { foreach (KeyValuePair item in textureCache) { if ((Object)(object)item.Value != (Object)null) { return item.Value; } } return null; } private static Texture2D LoadNamedTexture(Dictionary textureCache, PmxMaterialInfo info, string nameHint, ManualLogSource log) { if (info == null) { return null; } Texture2D val = LoadTexture(info.MainTexturePath, textureCache, log); if ((Object)(object)val != (Object)null) { return val; } Texture2D val2 = LoadTexture(info.ToonTexturePath, textureCache, log); if ((Object)(object)val2 != (Object)null && info.Name != null && info.Name.IndexOf(nameHint, StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } return null; } private static Texture2D LoadTexture(string fullPath, Dictionary textureCache, ManualLogSource log) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(fullPath)) { return null; } if (textureCache.TryGetValue(fullPath, out var value)) { return value; } if (!File.Exists(fullPath)) { textureCache[fullPath] = null; return null; } try { using FileStream fileStream = File.OpenRead(fullPath); 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, true, false); ((Object)val2).name = Path.GetFileNameWithoutExtension(fullPath); val2.SetPixels32(array); ((Texture)val2).filterMode = (FilterMode)2; ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).anisoLevel = 8; val2.Apply(true, false); textureCache[fullPath] = val2; return val2; } finally { ((IDisposable)val)?.Dispose(); } } catch (Exception ex) { if (log != null) { log.LogWarning((object)("Failed to load PMX texture '" + fullPath + "': " + ex.Message)); } textureCache[fullPath] = null; return null; } } private static Mesh BuildMesh(string meshName, Vector3[] positions, Vector3[] normals, Vector2[] uvs, int[] faceIndices, List materials) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Expected O, but got Unknown Mesh val = new Mesh(); ((Object)val).name = (string.IsNullOrEmpty(meshName) ? "FufuMesh" : meshName); if (positions.Length > 65535) { val.indexFormat = (IndexFormat)1; } val.vertices = positions; val.normals = normals; val.uv = uvs; val.subMeshCount = Mathf.Max(1, materials.Count); int num = 0; int num2 = Mathf.Max(1, materials.Count); for (int i = 0; i < num2; i++) { int num3 = ((i < materials.Count) ? materials[i].SurfaceIndexCount : (faceIndices.Length - num)); num3 = Mathf.Clamp(num3, 0, faceIndices.Length - num); int[] array = new int[num3]; for (int j = 0; j + 2 < num3; j += 3) { array[j] = faceIndices[num + j]; array[j + 1] = faceIndices[num + j + 2]; array[j + 2] = faceIndices[num + j + 1]; } val.SetTriangles(array, i, true); num += num3; } val.RecalculateBounds(); return val; } private static Shader FindCompatibleShader() { return Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard") ?? Shader.Find("W/Peak_Standard") ?? Shader.Find("Universal Render Pipeline/Unlit") ?? Shader.Find("Unlit/Texture"); } private static void ApplyTexture(Material material, Texture2D texture) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null) && !((Object)(object)texture == (Object)null)) { if (material.HasProperty("_BaseMap")) { material.SetTexture("_BaseMap", (Texture)(object)texture); material.SetTextureScale("_BaseMap", Vector2.one); material.SetTextureOffset("_BaseMap", Vector2.zero); } if (material.HasProperty("_MainTex")) { material.SetTexture("_MainTex", (Texture)(object)texture); material.SetTextureScale("_MainTex", Vector2.one); material.SetTextureOffset("_MainTex", Vector2.zero); } } } private static void ApplyColor(Material material, Color color) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { color.a = 1f; float num = (color.r + color.g + color.b) / 3f; float num2 = Mathf.Max(Mathf.Max(color.r, color.g), color.b); if (num > 0.5f) { float num3 = 0.94f; float num4 = num3 / Mathf.Max(num2, 0.001f); color.r = Mathf.Min(color.r * num4, num3); color.g = Mathf.Min(color.g * num4, num3); color.b = Mathf.Min(color.b * num4, num3); } else if (num > 0.25f) { float num5 = 0.88f / Mathf.Max(num, 0.001f); color.r = Mathf.Clamp01(color.r * num5); color.g = Mathf.Clamp01(color.g * num5); color.b = Mathf.Clamp01(color.b * num5); } else if (num2 < 0.3f) { color.r = 0.01f; color.g = 0.01f; color.b = 0.02f; } else { color.b = (color.g = (color.r = num * 0.9f)) + 0.01f; } if (material.HasProperty("_Tint")) { material.SetColor("_Tint", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } } } private static void ConfigureOpaqueSurface(Material material) { //IL_0196: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Surface")) { material.SetFloat("_Surface", 0f); } if (material.HasProperty("_Blend")) { material.SetFloat("_Blend", 0f); } if (material.HasProperty("_ZWrite")) { material.SetFloat("_ZWrite", 1f); } if (material.HasProperty("_SrcBlend")) { material.SetFloat("_SrcBlend", 1f); } if (material.HasProperty("_DstBlend")) { material.SetFloat("_DstBlend", 0f); } if (material.HasProperty("_Cull")) { material.SetFloat("_Cull", 0f); } 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.renderQueue = 2000; material.SetOverrideTag("RenderType", "Opaque"); material.DisableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_SURFACE_TYPE_OPAQUE"); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.DisableKeyword("_NORMALMAP"); material.DisableKeyword("_METALLICSPECGLOSSMAP"); material.DisableKeyword("_OCCLUSIONMAP"); } } private static string ResolveRelativePath(string baseDirectory, string relativePath) { if (string.IsNullOrEmpty(relativePath)) { return null; } string path = relativePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); return Path.GetFullPath(Path.Combine(baseDirectory, path)); } private static string GetTexturePath(List texturePaths, int index) { if (index < 0 || index >= texturePaths.Count) { return null; } return texturePaths[index]; } private static Vector3 ReadVector3(BinaryReader reader) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); } private static Vector2 ReadVector2(BinaryReader reader) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Vector2(reader.ReadSingle(), reader.ReadSingle()); } private static Vector3 ConvertPosition(Vector3 source) { //IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(source.x, source.y, 0f - source.z); } private static Vector3 ConvertNormal(Vector3 source) { //IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) return new Vector3(source.x, source.y, 0f - source.z); } private static Vector2 ConvertUv(Vector2 source) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new Vector2(source.x, 1f - source.y); } private static Vector3 CalculateMeshOffset(Bounds bounds, Vector3 recommendedBaseScale) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: 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_0032: Unknown result type (might be due to invalid IL or missing references) float num = ((Mathf.Abs(recommendedBaseScale.y) > 0.0001f) ? recommendedBaseScale.y : 1f); return ReferenceVisibleCenterAtBaseScale / num - ((Bounds)(ref bounds)).center; } private static Vector3 CalculateRecommendedBaseScale(float sourceHeight) { //IL_0035: 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_0012: Unknown result type (might be due to invalid IL or missing references) if (sourceHeight <= 0.0001f) { return Vector3.one * 0.09f; } float num = Mathf.Clamp(ReferenceVisibleSizeAtBaseScale.y / sourceHeight, 0.04f, 0.2f); return new Vector3(num, num, num); } private static int ReadUnsignedIndex(BinaryReader reader, int size) { return size switch { 1 => reader.ReadByte(), 2 => reader.ReadUInt16(), 4 => reader.ReadInt32(), _ => throw new InvalidDataException("Unsupported PMX unsigned index size: " + size), }; } private static int ReadSignedIndex(BinaryReader reader, int size) { return size switch { 1 => reader.ReadSByte(), 2 => reader.ReadInt16(), 4 => reader.ReadInt32(), _ => throw new InvalidDataException("Unsupported PMX signed index size: " + size), }; } private static bool IsFaceMaterial(string materialName) { if (!string.IsNullOrEmpty(materialName)) { if (materialName.IndexOf("face", StringComparison.OrdinalIgnoreCase) < 0 && materialName.IndexOf("head", StringComparison.OrdinalIgnoreCase) < 0) { return materialName.IndexOf("shy", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } private static bool IsIconMaterial(string materialName) { if (!string.IsNullOrEmpty(materialName)) { if (materialName.IndexOf("face", StringComparison.OrdinalIgnoreCase) < 0) { return materialName.IndexOf("shy", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } return false; } } [HarmonyPatch(typeof(Action_AskBingBong), "AskRoutine", new Type[] { typeof(int), typeof(bool) })] public static class Patch_AskRoutine { [CompilerGenerated] private sealed class <>c__DisplayClass11_0 { public string fileName; internal void b__0(AudioClip clip) { if ((Object)(object)clip != (Object)null) { CustomClips.Add(clip); ClipNames.Add(fileName); } } } [CompilerGenerated] private sealed class d__11 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (_hasLoadAttempt && !_isLoading) { return false; } if (_isLoading) { goto IL_0052; } _isLoading = true; _hasLoadAttempt = true; CustomClips.Clear(); ClipNames.Clear(); 5__2 = 0; goto IL_0107; case 1: <>1__state = -1; goto IL_0052; case 2: { <>1__state = -1; goto IL_00f7; } IL_00f7: 5__2++; goto IL_0107; IL_0107: if (5__2 < ExpectedFiles.Length) { <>c__DisplayClass11_0 CS$<>8__locals0 = new <>c__DisplayClass11_0 { fileName = ExpectedFiles[5__2] }; string text = Path.Combine(Plugin.directory, CS$<>8__locals0.fileName); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("[AudioPatch] Missing expected clip file: " + text)); goto IL_00f7; } <>2__current = LoadClip(text, delegate(AudioClip clip) { if ((Object)(object)clip != (Object)null) { CustomClips.Add(clip); ClipNames.Add(CS$<>8__locals0.fileName); } }); <>1__state = 2; return true; } Plugin.VerboseLog("[AudioPatch] Loaded custom clip count: " + CustomClips.Count); _isLoading = false; return false; IL_0052: if (_isLoading) { <>2__current = null; <>1__state = 1; return true; } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__12 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string filename; public Action onLoaded; private UnityWebRequest 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Uri uri = new Uri(filename); 5__2 = UnityWebRequestMultimedia.GetAudioClip(uri.AbsoluteUri, (AudioType)20); <>1__state = -3; <>2__current = 5__2.SendWebRequest(); <>1__state = 1; return true; } case 1: <>1__state = -3; if ((int)5__2.result == 1) { AudioClip content = DownloadHandlerAudioClip.GetContent(5__2); onLoaded(content); Plugin.VerboseLog("[AudioPatch] Loaded custom clip: " + filename); } else { onLoaded(null); Plugin.Log.LogError((object)("[AudioPatch] Failed to load audio clip: " + filename + " - " + 5__2.error)); } <>m__Finally1(); 5__2 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (5__2 != null) { ((IDisposable)5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__8 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action_AskBingBong instance; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; if ((Object)(object)instance == (Object)null) { return false; } <>2__current = EnsureClipsLoaded(); <>1__state = 1; return true; case 1: { <>1__state = -1; if (CustomClips.Count == 0) { Plugin.Log.LogWarning((object)"[AudioPatch] No custom clips found. Expected files like response_0.wav in plugin directory."); return false; } int nextClipIndex = _nextClipIndex; _nextClipIndex = (_nextClipIndex + 1) % CustomClips.Count; AudioClip val = CustomClips[nextClipIndex]; string text = ClipNames[nextClipIndex]; if ((Object)(object)val == (Object)null) { Plugin.Log.LogWarning((object)("[AudioPatch] Missing custom clip index " + nextClipIndex + ".")); return false; } AudioSource orCreatePlaybackSource = GetOrCreatePlaybackSource(instance); if ((Object)(object)orCreatePlaybackSource != (Object)null) { orCreatePlaybackSource.Stop(); orCreatePlaybackSource.clip = val; orCreatePlaybackSource.loop = false; orCreatePlaybackSource.pitch = 1f; orCreatePlaybackSource.Play(); Plugin.VerboseLog("[AudioPatch] Played custom BingBong clip: " + text); } else { Plugin.Log.LogWarning((object)"[AudioPatch] No safe playback AudioSource available."); } if ((Object)(object)instance.subtitles != (Object)null) { ((TMP_Text)instance.subtitles).text = Plugin.ReplacementDisplayName; <>2__current = (object)new WaitForSeconds(Mathf.Clamp(val.length, 0.5f, 4f)); <>1__state = 2; return true; } break; } case 2: <>1__state = -1; break; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string RuntimeSourceObjectName = "MikuBong_CustomAudio"; private static readonly string[] ExpectedFiles = new string[4] { "response_0.wav", "response_1.wav", "response_2.wav", "response_3.wav" }; private static readonly List CustomClips = new List(); private static readonly List ClipNames = new List(); private static bool _isLoading; private static bool _hasLoadAttempt; private static int _nextClipIndex; [HarmonyPrefix] public static bool Prefix(Action_AskBingBong __instance, int index, bool spamming, ref IEnumerator __result) { if ((Object)(object)__instance == (Object)null) { return true; } __result = PlayCustomRoutine(__instance, index); return false; } [IteratorStateMachine(typeof(d__8))] private static IEnumerator PlayCustomRoutine(Action_AskBingBong instance, int index) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { instance = instance }; } private static AudioSource GetOrCreatePlaybackSource(Action_AskBingBong instance) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null) { return null; } Transform val = ((Component)instance).transform.Find("MikuBong_CustomAudio"); AudioSource val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : null); if ((Object)(object)val2 == (Object)null) { GameObject val3 = new GameObject("MikuBong_CustomAudio"); val3.transform.SetParent(((Component)instance).transform, false); val2 = val3.AddComponent(); } ConfigurePlaybackSource(val2, instance.source); return val2; } private static void ConfigurePlaybackSource(AudioSource playbackSource, AudioSource template) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052->IL0052: Incompatible stack types: O vs I4 //IL_004c->IL0052: Incompatible stack types: I4 vs O //IL_004c->IL0052: Incompatible stack types: O vs I4 if (!((Object)(object)playbackSource == (Object)null)) { playbackSource.playOnAwake = false; playbackSource.loop = false; playbackSource.pitch = 1f; playbackSource.spatialBlend = (((Object)(object)template != (Object)null) ? template.spatialBlend : 1f); object obj = playbackSource; int num; if ((Object)(object)template != (Object)null) { obj = template.rolloffMode; num = (int)obj; } else { num = 0; obj = num; num = (int)obj; } ((AudioSource)num).rolloffMode = (AudioRolloffMode)obj; playbackSource.minDistance = (((Object)(object)template != (Object)null) ? template.minDistance : 1f); playbackSource.maxDistance = (((Object)(object)template != (Object)null) ? template.maxDistance : 20f); playbackSource.spread = (((Object)(object)template != (Object)null) ? template.spread : 0f); playbackSource.volume = (((Object)(object)template != (Object)null) ? template.volume : 1f); playbackSource.dopplerLevel = (((Object)(object)template != (Object)null) ? template.dopplerLevel : 0f); playbackSource.priority = (((Object)(object)template != (Object)null) ? template.priority : 128); } } [IteratorStateMachine(typeof(d__11))] private static IEnumerator EnsureClipsLoaded() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(0); } [IteratorStateMachine(typeof(d__12))] private static IEnumerator LoadClip(string filename, Action onLoaded) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__12(0) { filename = filename, onLoaded = onLoaded }; } } }