Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of MeshVault v1.0.9
Plugins/MeshVault.Il2Cpp.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using Il2CppInterop.Runtime.InteropTypes.Arrays; using MelonLoader; using MeshVault; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering.Universal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(MeshVaultPlugin), "MeshVault", "1.0.8", "hdlmrell", null)] [assembly: MelonColor(255, 100, 149, 237)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MeshVault { public class MeshVaultPlugin : MelonPlugin { public override void OnPreInitialization() { } } internal static class JsonParser { internal static void ParseDatabase(string json, Dictionary<string, MeshEntry> db) { int pos = 0; int length = json.Length; SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != '{') { return; } pos++; while (pos < length) { SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] == '}') { break; } if (json[pos] == ',') { pos++; continue; } string text = ReadJsonString(json, ref pos, length); if (text == null) { break; } SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != ':') { break; } pos++; SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != '{') { break; } int num = pos; int num2 = 1; pos++; while (pos < length && num2 > 0) { if (json[pos] == '{') { num2++; } else if (json[pos] == '}') { num2--; } if (num2 > 0) { pos++; } } if (pos < length) { pos++; MeshEntry meshEntry = ParseEntry(json.Substring(num, pos - num)); if (meshEntry != null) { db[text] = meshEntry; } continue; } break; } } private static MeshEntry ParseEntry(string json) { MeshEntry meshEntry = new MeshEntry(); try { string json2 = json; int num = json.IndexOf("\"childMeshes\"", StringComparison.Ordinal); if (num >= 0) { json2 = json.Substring(0, num) + "}"; } meshEntry.Vertices = ParseVec3Array(ExtractArrayValue(json2, "vertices")); meshEntry.Normals = ParseVec3Array(ExtractArrayValue(json2, "normals")); meshEntry.UVs = ParseVec2Array(ExtractArrayValue(json2, "uvs")); meshEntry.Triangles = ParseIntArray(ExtractArrayValue(json2, "triangles")); meshEntry.MaterialName = ExtractStringValue(json2, "materialName") ?? "Standard"; meshEntry.ShaderName = ExtractStringValue(json2, "shaderName") ?? "Standard"; meshEntry.Color = ParseFloatArray(ExtractArrayValue(json2, "color")) ?? MeshVaultAPI.DefaultColor; meshEntry.BoundsCenter = ParseFloatArray(ExtractArrayValue(json2, "boundsCenter")) ?? new float[3]; meshEntry.BoundsSize = ParseFloatArray(ExtractArrayValue(json2, "boundsSize")) ?? new float[3] { 1f, 1f, 1f }; int[] array = ParseIntArray(ExtractArrayValue(json2, "subMeshTriCounts")); if (array != null && array.Length != 0) { meshEntry.SubMeshTriCounts = array; meshEntry.SubMeshMaterialNames = ParseStringArray(ExtractArrayValue(json2, "subMeshMaterialNames")); meshEntry.SubMeshShaderNames = ParseStringArray(ExtractArrayValue(json2, "subMeshShaderNames")); meshEntry.SubMeshTextureNames = ParseStringArray(ExtractArrayValue(json2, "subMeshTextureNames")); meshEntry.SubMeshColorTints = ParseFloat4ArrayOfArrays(ExtractArrayValue(json2, "subMeshColorTints")); } string text = ExtractStringValue(json2, "textureName"); meshEntry.TextureName = (string.IsNullOrEmpty(text) ? null : text); meshEntry.BakedColorTint = ParseFloatArray(ExtractArrayValue(json2, "bakedColorTint")); meshEntry.ColorTint = ParseFloatArray(ExtractArrayValue(json2, "colorTint")); meshEntry.Metallic = ExtractFloatValue(json2, "metallic"); meshEntry.Smoothness = ExtractFloatValue(json2, "smoothness"); meshEntry.EmissiveColor = ParseFloatArray(ExtractArrayValue(json2, "emissiveColor")); meshEntry.EmissiveIntensity = ExtractFloatValue(json2, "emissiveIntensity"); meshEntry.ChildMeshes = ParseChildMeshArray(json); return meshEntry; } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Warning("Parse entry failed: " + ex.Message); return null; } } internal static string ExtractArrayValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length || json[num] != '[') { return null; } int num2 = num; int num3 = 1; for (num++; num < json.Length; num++) { if (num3 <= 0) { break; } if (json[num] == '[') { num3++; } else if (json[num] == ']') { num3--; } } return json.Substring(num2, num - num2); } internal static string ExtractStringValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length || json[num] != '"') { return null; } int pos = num; return ReadJsonString(json, ref pos, json.Length); } internal static float? ExtractFloatValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length) { return null; } int num2 = num; for (; num < json.Length && json[num] != ',' && json[num] != '}' && json[num] != '\n' && json[num] != '\r'; num++) { } string text2 = json.Substring(num2, num - num2).Trim(); if (string.IsNullOrEmpty(text2) || text2 == "null") { return null; } if (float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return null; } private static Vector3[] ParseVec3Array(string arrayStr) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(arrayStr)) { return (Vector3[])(object)new Vector3[0]; } List<Vector3> list = new List<Vector3>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string[] array = arrayStr.Substring(num2 + 1, num3 - num2 - 1).Split(','); if (array.Length >= 3) { list.Add(new Vector3(float.Parse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture))); } num = num3 + 1; } return list.ToArray(); } private static Vector2[] ParseVec2Array(string arrayStr) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(arrayStr)) { return (Vector2[])(object)new Vector2[0]; } List<Vector2> list = new List<Vector2>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string[] array = arrayStr.Substring(num2 + 1, num3 - num2 - 1).Split(','); if (array.Length >= 2) { list.Add(new Vector2(float.Parse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture))); } num = num3 + 1; } return list.ToArray(); } private static int[] ParseIntArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return new int[0]; } arrayStr = arrayStr.Trim(); if (arrayStr.StartsWith("[")) { arrayStr = arrayStr.Substring(1); } if (arrayStr.EndsWith("]")) { arrayStr = arrayStr.Substring(0, arrayStr.Length - 1); } string[] array = arrayStr.Split(','); List<int> list = new List<int>(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (text.Length > 0 && int.TryParse(text, out var result)) { list.Add(result); } } return list.ToArray(); } private static float[] ParseFloatArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } arrayStr = arrayStr.Trim(); if (arrayStr.StartsWith("[")) { arrayStr = arrayStr.Substring(1); } if (arrayStr.EndsWith("]")) { arrayStr = arrayStr.Substring(0, arrayStr.Length - 1); } string[] array = arrayStr.Split(','); List<float> list = new List<float>(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i].Trim(); if (text.Length > 0 && float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { list.Add(result); } } return list.ToArray(); } private static string[] ParseStringArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } List<string> list = new List<string>(); int i = 0; int length; for (length = arrayStr.Length; i < length && arrayStr[i] != '['; i++) { } if (i < length) { i++; } while (i < length) { SkipWhitespace(arrayStr, ref i, length); if (i >= length || arrayStr[i] == ']') { break; } if (arrayStr[i] == ',') { i++; continue; } string text = ReadJsonString(arrayStr, ref i, length); if (text == null) { break; } list.Add(text); } if (list.Count <= 0) { return null; } return list.ToArray(); } private static float[][] ParseFloat4ArrayOfArrays(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } List<float[]> list = new List<float[]>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string[] array = arrayStr.Substring(num2 + 1, num3 - num2 - 1).Split(','); if (array.Length >= 4) { list.Add(new float[4] { float.Parse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture) }); } num = num3 + 1; } if (list.Count <= 0) { return null; } return list.ToArray(); } private static ChildMeshEntry[] ParseChildMeshArray(string json) { string text = "\"childMeshes\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && json[num] != '['; num++) { } if (num >= json.Length) { return null; } int num2 = num; int num3 = 1; for (num++; num < json.Length; num++) { if (num3 <= 0) { break; } if (json[num] == '[') { num3++; } else if (json[num] == ']') { num3--; } } string text2 = json.Substring(num2 + 1, num - num2 - 2); List<ChildMeshEntry> list = new List<ChildMeshEntry>(); int num4 = 0; while (num4 < text2.Length) { int num5 = text2.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int i; for (i = num5 + 1; i < text2.Length; i++) { if (num6 <= 0) { break; } if (text2[i] == '{') { num6++; } else if (text2[i] == '}') { num6--; } } string json2 = text2.Substring(num5, i - num5); try { ChildMeshEntry item = new ChildMeshEntry { Vertices = ParseVec3Array(ExtractArrayValue(json2, "vertices")), Normals = ParseVec3Array(ExtractArrayValue(json2, "normals")), UVs = ParseVec2Array(ExtractArrayValue(json2, "uvs")), Triangles = ParseIntArray(ExtractArrayValue(json2, "triangles")), MaterialName = (ExtractStringValue(json2, "materialName") ?? "Standard"), ShaderName = (ExtractStringValue(json2, "shaderName") ?? "Standard"), Color = (ParseFloatArray(ExtractArrayValue(json2, "color")) ?? MeshVaultAPI.DefaultColor), ColorTint = ParseFloatArray(ExtractArrayValue(json2, "colorTint")), Metallic = ExtractFloatValue(json2, "metallic"), Smoothness = ExtractFloatValue(json2, "smoothness"), EmissiveColor = ParseFloatArray(ExtractArrayValue(json2, "emissiveColor")), EmissiveIntensity = ExtractFloatValue(json2, "emissiveIntensity") }; list.Add(item); } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Warning("Parse child mesh failed: " + ex.Message); } num4 = i; } if (list.Count <= 0) { return null; } return list.ToArray(); } private static void SkipWhitespace(string s, ref int pos, int len) { while (pos < len && (s[pos] == ' ' || s[pos] == '\t' || s[pos] == '\n' || s[pos] == '\r')) { pos++; } } private static string ReadJsonString(string s, ref int pos, int len) { SkipWhitespace(s, ref pos, len); if (pos >= len || s[pos] != '"') { return null; } pos++; StringBuilder stringBuilder = new StringBuilder(); while (pos < len) { char c = s[pos]; if (c == '\\' && pos + 1 < len) { pos++; stringBuilder.Append(s[pos]); } else { if (c == '"') { pos++; return stringBuilder.ToString(); } stringBuilder.Append(c); } pos++; } return stringBuilder.ToString(); } } public class ChildMeshEntry { public Vector3[] Vertices; public Vector3[] Normals; public Vector2[] UVs; public int[] Triangles; public string MaterialName; public string ShaderName; public float[] Color; public float[] ColorTint; public float? Metallic; public float? Smoothness; public float[] EmissiveColor; public float? EmissiveIntensity; } public class MeshEntry { public Vector3[] Vertices; public Vector3[] Normals; public Vector2[] UVs; public int[] Triangles; public string MaterialName; public string ShaderName; public float[] Color; public float[] BoundsCenter; public float[] BoundsSize; public int[] SubMeshTriCounts; public string[] SubMeshMaterialNames; public string[] SubMeshShaderNames; public string TextureName; public float[] BakedColorTint; public string[] SubMeshTextureNames; public float[][] SubMeshColorTints; public float[] ColorTint; public float? Metallic; public float? Smoothness; public float[] EmissiveColor; public float? EmissiveIntensity; public ChildMeshEntry[] ChildMeshes; } public static class MeshVaultAPI { private const string EmbeddedResourceName = "MeshVault.Resources.MeshDatabase.json"; private const string URPLitShader = "Universal Render Pipeline/Lit"; private const string URPSimpleLitShader = "Universal Render Pipeline/Simple Lit"; private const string StandardShader = "Standard"; private const string WorldspaceUVShaderTag = "WorldspaceUV"; private const string ShaderPropBaseMap = "_BaseMap"; private const string ShaderPropBaseColor = "_BaseColor"; private const string ShaderPropMetallic = "_Metallic"; private const string ShaderPropSmoothness = "_Smoothness"; private const float DefaultMetallic = 0f; private const float DefaultSmoothness = 0.1f; private const string ShaderPropEmissionColor = "_EmissionColor"; private const string ShaderKeywordEmission = "_EMISSION"; private const float BakedSmoothness = 0f; internal const string DecalPropBaseMap = "_Base_Map"; internal const string DecalPropColor = "_Color"; internal const float DecalDepth = 0.1f; private const string ApiLogPrefix = "[MeshVaultAPI]"; internal static readonly float[] DefaultColor = new float[4] { 1f, 1f, 1f, 1f }; private static Dictionary<string, MeshEntry> _cache; private static bool _loaded; private static readonly Dictionary<string, string> _registeredPrefixes = new Dictionary<string, string>(); private static readonly Dictionary<string, string> _registeredDecalPrefixes = new Dictionary<string, string>(); private static readonly Dictionary<string, Texture2D> _decalRegistry = new Dictionary<string, Texture2D>(); private static readonly Dictionary<string, Material> _materialCache = new Dictionary<string, Material>(); private static readonly Dictionary<string, Texture> _textureCache = new Dictionary<string, Texture>(); private static readonly HashSet<string> _materialBlacklist = new HashSet<string> { "SM_AC_Impostor", "filing cabinet mat", "mastermat1", "pallet rack mat", "pallet mat", "PolygonGangWarfare_Material_01_A", "PropsMat", "small bin mat", "rubbish bin mat" }; private static Material _decalBaseMaterial; private static string DiskPath => Path.Combine(Application.dataPath, "..", "UserData", "MeshVault", "MeshDatabase.json"); private static string DataDir => Path.Combine(Application.dataPath, "..", "UserData", "MeshVault"); public static void Init() { if (_loaded) { return; } _cache = new Dictionary<string, MeshEntry>(); try { string fullPath = Path.GetFullPath(DataDir); if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); } } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Error("Failed to create data directory: " + ex.Message); } string fullPath2 = Path.GetFullPath(DiskPath); if (File.Exists(fullPath2)) { try { JsonParser.ParseDatabase(File.ReadAllText(fullPath2), _cache); Melon<MeshVaultPlugin>.Logger.Msg($"Loaded {_cache.Count} mesh entries from disk: {fullPath2}"); _loaded = true; return; } catch (Exception ex2) { Melon<MeshVaultPlugin>.Logger.Error("Failed to load from disk: " + ex2.Message); } } try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MeshVault.Resources.MeshDatabase.json"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); JsonParser.ParseDatabase(Encoding.UTF8.GetString(array), _cache); Melon<MeshVaultPlugin>.Logger.Msg($"Loaded {_cache.Count} mesh entries from embedded resource"); } else { Melon<MeshVaultPlugin>.Logger.Msg("No MeshDatabase.json found (disk or embedded) — starting with empty cache"); } } catch (Exception ex3) { Melon<MeshVaultPlugin>.Logger.Error("Failed to load from embedded resource: " + ex3.Message); } _loaded = true; } public static bool HasMesh(string id) { EnsureLoaded(); return _cache.ContainsKey(id); } public static MeshEntry GetMesh(string id) { EnsureLoaded(); if (!_cache.TryGetValue(id, out var value)) { return null; } return value; } public static string[] ListMeshes() { EnsureLoaded(); string[] array = new string[_cache.Count]; _cache.Keys.CopyTo(array, 0); return array; } public static Dictionary<string, MeshEntry> GetAllEntries() { EnsureLoaded(); return _cache; } public static Dictionary<string, float[]> BuildMaterialCatalog() { EnsureLoaded(); Dictionary<string, float[]> dictionary = new Dictionary<string, float[]>(); foreach (KeyValuePair<string, MeshEntry> item in _cache) { MeshEntry value = item.Value; if (!string.IsNullOrEmpty(value.MaterialName) && !dictionary.ContainsKey(value.MaterialName) && !_materialBlacklist.Contains(value.MaterialName)) { dictionary[value.MaterialName] = value.Color ?? DefaultColor; } if (value.SubMeshMaterialNames != null) { for (int i = 0; i < value.SubMeshMaterialNames.Length; i++) { string text = value.SubMeshMaterialNames[i]; if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text) && !_materialBlacklist.Contains(text)) { float[] value2 = ((value.SubMeshColorTints != null && i < value.SubMeshColorTints.Length && value.SubMeshColorTints[i] != null) ? value.SubMeshColorTints[i] : (value.Color ?? DefaultColor)); dictionary[text] = value2; } } } if (value.ChildMeshes == null) { continue; } ChildMeshEntry[] childMeshes = value.ChildMeshes; foreach (ChildMeshEntry childMeshEntry in childMeshes) { if (!string.IsNullOrEmpty(childMeshEntry.MaterialName) && !dictionary.ContainsKey(childMeshEntry.MaterialName) && !_materialBlacklist.Contains(childMeshEntry.MaterialName)) { dictionary[childMeshEntry.MaterialName] = childMeshEntry.Color ?? DefaultColor; } } } return dictionary; } public static void SetEntry(string id, MeshEntry entry) { EnsureLoaded(); _cache[id] = entry; } public static void InvalidateCache() { _cache = null; _loaded = false; _materialCache.Clear(); _textureCache.Clear(); } private static void EnsureLoaded() { if (!_loaded) { Init(); } } public static int RegisterMeshes(string prefix, string modName, string json) { EnsureLoaded(); if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(modName) || string.IsNullOrEmpty(json)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: prefix, modName, and json are required"); return -1; } foreach (char c in prefix) { if (!char.IsLetterOrDigit(c) || char.IsUpper(c)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: prefix \"" + prefix + "\" is invalid — must be lowercase alphanumeric only"); return -1; } } if (_registeredPrefixes.TryGetValue(prefix, out var value)) { Melon<MeshVaultPlugin>.Logger.Error($"{"[MeshVaultAPI]"} RegisterMeshes: prefix \"{prefix}\" is already claimed by \"{value}\""); return -1; } Dictionary<string, MeshEntry> dictionary = new Dictionary<string, MeshEntry>(); try { JsonParser.ParseDatabase(json, dictionary); } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Error($"{"[MeshVaultAPI]"} RegisterMeshes: failed to parse JSON from \"{modName}\": {ex.Message}"); return -1; } if (dictionary.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterMeshes: JSON from \"" + modName + "\" contained no entries"); return 0; } string value2 = prefix + "_"; foreach (string key in dictionary.Keys) { if (!key.StartsWith(value2)) { Melon<MeshVaultPlugin>.Logger.Error($"{"[MeshVaultAPI]"} RegisterMeshes: entry \"{key}\" does not start with \"{value2}\" — all entries from \"{modName}\" must use this prefix"); return -1; } } _registeredPrefixes[prefix] = modName; int num = 0; foreach (KeyValuePair<string, MeshEntry> item in dictionary) { if (_cache.ContainsKey(item.Key)) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterMeshes: entry \"" + item.Key + "\" already exists — skipping"); continue; } _cache[item.Key] = item.Value; num++; } Melon<MeshVaultPlugin>.Logger.Msg($"{"[MeshVaultAPI]"} Registered {num} mesh entries from \"{modName}\" (prefix: \"{prefix}\")"); return num; } public static bool IsPrefixRegistered(string prefix) { return _registeredPrefixes.ContainsKey(prefix); } public static int RegisterDecals(string prefix, string modName, Dictionary<string, byte[]> textures) { //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Expected O, but got Unknown if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(modName) || textures == null) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: prefix, modName, and textures are required"); return -1; } foreach (char c in prefix) { if (!char.IsLetterOrDigit(c) || char.IsUpper(c)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: prefix \"" + prefix + "\" is invalid — must be lowercase alphanumeric only"); return -1; } } if (_registeredDecalPrefixes.TryGetValue(prefix, out var value)) { Melon<MeshVaultPlugin>.Logger.Error($"{"[MeshVaultAPI]"} RegisterDecals: prefix \"{prefix}\" is already claimed by \"{value}\""); return -1; } if (textures.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: no textures provided by \"" + modName + "\""); return 0; } _registeredDecalPrefixes[prefix] = modName; int num = 0; string text = prefix + "_"; foreach (KeyValuePair<string, byte[]> texture in textures) { string text2 = (texture.Key.StartsWith(text) ? texture.Key : (text + texture.Key)); if (_decalRegistry.ContainsKey(text2)) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: decal \"" + text2 + "\" already exists — skipping"); continue; } byte[] value2 = texture.Value; if (value2 == null || value2.Length == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: decal \"" + text2 + "\" has empty data — skipping"); continue; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(value2))) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: failed to load image data for \"" + text2 + "\""); Object.Destroy((Object)(object)val); continue; } ((Object)val).name = text2; ((Texture)val).filterMode = (FilterMode)1; _decalRegistry[text2] = val; num++; } if (num == 0) { _registeredDecalPrefixes.Remove(prefix); } Melon<MeshVaultPlugin>.Logger.Msg($"{"[MeshVaultAPI]"} Registered {num} decal(s) from \"{modName}\" (prefix: \"{prefix}\")"); return num; } public static int RegisterDecals(string prefix, string modName, Assembly assembly, string resourcePrefix = null) { if (assembly == null) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: assembly is required"); return -1; } Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>(); string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (resourcePrefix != null && !text.StartsWith(resourcePrefix)) { continue; } string text2 = text.ToLowerInvariant(); if (!text2.EndsWith(".png") && !text2.EndsWith(".jpg") && !text2.EndsWith(".jpeg")) { continue; } string text3 = text; if (resourcePrefix != null && text3.StartsWith(resourcePrefix)) { text3 = text3.Substring(resourcePrefix.Length); } int num = text3.LastIndexOf('.'); if (num > 0) { text3 = text3.Substring(0, num); } using Stream stream = assembly.GetManifestResourceStream(text); if (stream != null) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); dictionary[text3] = memoryStream.ToArray(); } } if (dictionary.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: no image resources found in assembly \"" + assembly.GetName().Name + "\"" + ((resourcePrefix != null) ? (" with prefix \"" + resourcePrefix + "\"") : "")); return 0; } return RegisterDecals(prefix, modName, dictionary); } public static string[] ListRegisteredDecals() { string[] array = new string[_decalRegistry.Count]; _decalRegistry.Keys.CopyTo(array, 0); return array; } public static Texture2D GetRegisteredDecal(string id) { if (!_decalRegistry.TryGetValue(id, out var value)) { return null; } return value; } public static bool IsDecalPrefixRegistered(string prefix) { return _registeredDecalPrefixes.ContainsKey(prefix); } internal static bool RegisterDecalDirect(string id, Texture2D tex) { if (string.IsNullOrEmpty(id) || (Object)(object)tex == (Object)null) { return false; } if (_decalRegistry.ContainsKey(id)) { return false; } _decalRegistry[id] = tex; return true; } public static GameObject Spawn(string id, Vector3 position, Quaternion rotation, Transform parent = null, string namePrefix = "MeshVault", string[] materialOverrides = null, Color?[] colorOverrides = null) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Expected O, but got Unknown //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Unknown result type (might be due to invalid IL or missing references) //IL_03df: Expected O, but got Unknown //IL_0498: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04af: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Unknown result type (might be due to invalid IL or missing references) //IL_0681: Unknown result type (might be due to invalid IL or missing references) //IL_068b: Expected O, but got Unknown //IL_069d: Unknown result type (might be due to invalid IL or missing references) //IL_06d3: Unknown result type (might be due to invalid IL or missing references) //IL_055d: Unknown result type (might be due to invalid IL or missing references) //IL_0564: Expected O, but got Unknown //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_0781: Unknown result type (might be due to invalid IL or missing references) //IL_0788: Expected O, but got Unknown //IL_0793: Unknown result type (might be due to invalid IL or missing references) //IL_05a9: Unknown result type (might be due to invalid IL or missing references) //IL_07bb: Unknown result type (might be due to invalid IL or missing references) MeshEntry mesh = GetMesh(id); if (mesh == null) { Melon<MeshVaultPlugin>.Logger.Warning("Entry \"" + id + "\" not found"); return null; } Mesh val = new Mesh(); ((Object)val).name = "MV_" + id; val.vertices = Il2CppStructArray<Vector3>.op_Implicit(mesh.Vertices); val.normals = Il2CppStructArray<Vector3>.op_Implicit(mesh.Normals); val.uv = Il2CppStructArray<Vector2>.op_Implicit(mesh.UVs); Material[] array2; if (mesh.SubMeshTriCounts != null && mesh.SubMeshTriCounts.Length != 0) { int num2 = (val.subMeshCount = mesh.SubMeshTriCounts.Length); int num3 = 0; for (int i = 0; i < num2; i++) { int num4 = mesh.SubMeshTriCounts[i]; int[] array = new int[num4]; Array.Copy(mesh.Triangles, num3, array, 0, num4); val.SetTriangles(Il2CppStructArray<int>.op_Implicit(array), i); num3 += num4; } array2 = (Material[])(object)new Material[num2]; for (int j = 0; j < num2; j++) { Material val2 = null; bool alreadyCloned = false; if (materialOverrides != null && j < materialOverrides.Length && materialOverrides[j] != null) { val2 = FindSceneMaterial(materialOverrides[j]); } if ((Object)(object)val2 == (Object)null && ((mesh.SubMeshShaderNames != null && j < mesh.SubMeshShaderNames.Length) ? mesh.SubMeshShaderNames[j] : "").Contains("WorldspaceUV")) { string text = ((mesh.SubMeshTextureNames != null && j < mesh.SubMeshTextureNames.Length && !string.IsNullOrEmpty(mesh.SubMeshTextureNames[j])) ? mesh.SubMeshTextureNames[j] : mesh.TextureName); float[] colorTint = ((mesh.SubMeshColorTints != null && j < mesh.SubMeshColorTints.Length && mesh.SubMeshColorTints[j] != null) ? mesh.SubMeshColorTints[j] : mesh.BakedColorTint); if (!string.IsNullOrEmpty(text)) { val2 = CreateBakedMaterial(text, colorTint); alreadyCloned = (Object)(object)val2 != (Object)null; } } if ((Object)(object)val2 == (Object)null) { val2 = FindSceneMaterial((mesh.SubMeshMaterialNames != null && j < mesh.SubMeshMaterialNames.Length) ? mesh.SubMeshMaterialNames[j] : mesh.MaterialName); if ((Object)(object)val2 == (Object)null) { val2 = CreateFallbackMaterial(mesh); alreadyCloned = true; } } array2[j] = ApplyMaterialOverrides(val2, mesh.ColorTint, mesh.Metallic, mesh.Smoothness, mesh.EmissiveColor, mesh.EmissiveIntensity, alreadyCloned); } } else { val.triangles = Il2CppStructArray<int>.op_Implicit(mesh.Triangles); Material val3 = null; bool alreadyCloned2 = false; if (materialOverrides != null && materialOverrides.Length != 0 && materialOverrides[0] != null) { val3 = FindSceneMaterial(materialOverrides[0]); } if ((Object)(object)val3 == (Object)null && !string.IsNullOrEmpty(mesh.TextureName)) { val3 = CreateBakedMaterial(mesh.TextureName, mesh.BakedColorTint); alreadyCloned2 = (Object)(object)val3 != (Object)null; } if ((Object)(object)val3 == (Object)null) { val3 = FindSceneMaterial(mesh.MaterialName); if ((Object)(object)val3 == (Object)null) { val3 = CreateFallbackMaterial(mesh); alreadyCloned2 = true; } } array2 = (Material[])(object)new Material[1] { ApplyMaterialOverrides(val3, mesh.ColorTint, mesh.Metallic, mesh.Smoothness, mesh.EmissiveColor, mesh.EmissiveIntensity, alreadyCloned2) }; } val.RecalculateBounds(); GameObject val4 = new GameObject(namePrefix + "_" + id); val4.AddComponent<MeshFilter>().sharedMesh = val; ((Renderer)val4.AddComponent<MeshRenderer>()).sharedMaterials = Il2CppReferenceArray<Material>.op_Implicit(array2); val4.AddComponent<MeshCollider>().sharedMesh = val; val4.transform.position = position; val4.transform.rotation = rotation; if ((Object)(object)parent != (Object)null) { val4.transform.SetParent(parent, true); } if (mesh.ChildMeshes != null) { for (int k = 0; k < mesh.ChildMeshes.Length; k++) { ChildMeshEntry childMeshEntry = mesh.ChildMeshes[k]; if (childMeshEntry.Vertices == null || childMeshEntry.Vertices.Length == 0) { continue; } Mesh val5 = new Mesh(); ((Object)val5).name = $"MV_{id}_child{k}"; val5.vertices = Il2CppStructArray<Vector3>.op_Implicit(childMeshEntry.Vertices); val5.normals = Il2CppStructArray<Vector3>.op_Implicit(childMeshEntry.Normals); val5.uv = Il2CppStructArray<Vector2>.op_Implicit(childMeshEntry.UVs); val5.triangles = Il2CppStructArray<int>.op_Implicit(childMeshEntry.Triangles); val5.RecalculateBounds(); GameObject val6 = new GameObject($"child_{k}"); val6.transform.SetParent(val4.transform, false); val6.AddComponent<MeshFilter>().sharedMesh = val5; val6.AddComponent<MeshCollider>().sharedMesh = val5; MeshRenderer obj = val6.AddComponent<MeshRenderer>(); int num5 = ((mesh.SubMeshTriCounts != null && mesh.SubMeshTriCounts.Length != 0) ? (mesh.SubMeshTriCounts.Length + k) : (1 + k)); Material val7 = null; if (materialOverrides != null && num5 < materialOverrides.Length && materialOverrides[num5] != null) { val7 = FindSceneMaterial(materialOverrides[num5]); } bool alreadyCloned3 = false; Material val8; if ((Object)(object)val7 != (Object)null) { val8 = val7; } else { Material val9 = FindSceneMaterial(childMeshEntry.MaterialName); if (val9 != null) { val8 = val9; } else { val8 = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard")); float[] array3 = childMeshEntry.Color ?? DefaultColor; val8.color = new Color(array3[0], array3[1], array3[2], array3[3]); if (val8.HasProperty("_BaseColor")) { val8.SetColor("_BaseColor", val8.color); } if (val8.HasProperty("_Metallic")) { val8.SetFloat("_Metallic", 0f); } if (val8.HasProperty("_Smoothness")) { val8.SetFloat("_Smoothness", 0.1f); } alreadyCloned3 = true; } } ((Renderer)obj).sharedMaterial = ApplyMaterialOverrides(val8, childMeshEntry.ColorTint, childMeshEntry.Metallic, childMeshEntry.Smoothness, childMeshEntry.EmissiveColor, childMeshEntry.EmissiveIntensity, alreadyCloned3); } } if (colorOverrides != null) { MeshRenderer component = val4.GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null) { Il2CppReferenceArray<Material> sharedMaterials = ((Renderer)component).sharedMaterials; for (int l = 0; l < ((Il2CppArrayBase<Material>)(object)sharedMaterials).Length && l < colorOverrides.Length; l++) { if (colorOverrides[l].HasValue) { ((Il2CppArrayBase<Material>)(object)sharedMaterials)[l] = new Material(((Il2CppArrayBase<Material>)(object)sharedMaterials)[l]); ((Il2CppArrayBase<Material>)(object)sharedMaterials)[l].color = colorOverrides[l].Value; if (((Il2CppArrayBase<Material>)(object)sharedMaterials)[l].HasProperty("_BaseColor")) { ((Il2CppArrayBase<Material>)(object)sharedMaterials)[l].SetColor("_BaseColor", colorOverrides[l].Value); } } } ((Renderer)component).sharedMaterials = sharedMaterials; } int num6 = ((mesh.SubMeshTriCounts == null || mesh.SubMeshTriCounts.Length == 0) ? 1 : mesh.SubMeshTriCounts.Length); if (mesh.ChildMeshes != null) { for (int m = 0; m < mesh.ChildMeshes.Length; m++) { int num7 = num6 + m; if (num7 >= colorOverrides.Length || !colorOverrides[num7].HasValue) { continue; } Transform child = val4.transform.GetChild(m); MeshRenderer val10 = ((child != null) ? ((Component)child).GetComponent<MeshRenderer>() : null); if (!((Object)(object)val10 == (Object)null)) { Material val11 = new Material(((Renderer)val10).sharedMaterial); val11.color = colorOverrides[num7].Value; if (val11.HasProperty("_BaseColor")) { val11.SetColor("_BaseColor", colorOverrides[num7].Value); } ((Renderer)val10).sharedMaterial = val11; } } } } return val4; } public static GameObject SpawnDecal(string textureName, Vector3 position, Quaternion rotation, Color? tintColor = null, Vector3? scale = null, Transform parent = null) { //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00a0: 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_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011a: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) Texture2D val = (Texture2D)(((object)GetRegisteredDecal(textureName)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if ((Object)(object)val == (Object)null) { Melon<MeshVaultPlugin>.Logger.Warning("Decal texture \"" + textureName + "\" not found"); return null; } Material val2 = FindDecalBaseMaterial(); if ((Object)(object)val2 == (Object)null) { Melon<MeshVaultPlugin>.Logger.Warning("No decal shader found in scene"); return null; } GameObject val3 = new GameObject("MV_Decal_" + textureName); DecalProjector obj = val3.AddComponent<DecalProjector>(); Material val4 = new Material(val2); val4.SetTexture("_Base_Map", (Texture)(object)val); val4.SetColor("_Color", (Color)(((??)tintColor) ?? Color.white)); if (val4.HasProperty("_Normal_Map")) { val4.SetTexture("_Normal_Map", (Texture)null); } if (val4.HasProperty("_NormalMap")) { val4.SetTexture("_NormalMap", (Texture)null); } if (val4.HasProperty("_BumpMap")) { val4.SetTexture("_BumpMap", (Texture)null); } obj.material = val4; Vector3 val5 = (Vector3)(((??)scale) ?? Vector3.one); obj.size = new Vector3(val5.x, val5.y, 0.1f); obj.pivot = new Vector3(0f, 0f, 0.05f); obj.fadeFactor = 1f; obj.renderingLayerMask = uint.MaxValue; val3.transform.position = position; val3.transform.rotation = rotation; if ((Object)(object)parent != (Object)null) { val3.transform.SetParent(parent, true); } return val3; } private static Material FindDecalBaseMaterial() { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown if ((Object)(object)_decalBaseMaterial != (Object)null) { return _decalBaseMaterial; } foreach (DecalProjector item in Object.FindObjectsOfType<DecalProjector>(true)) { if ((Object)(object)item != (Object)null && (Object)(object)item.material != (Object)null && (Object)(object)item.material.shader != (Object)null) { _decalBaseMaterial = new Material(item.material); return _decalBaseMaterial; } } Shader val = Shader.Find("Shader Graphs/Decal") ?? Shader.Find("Universal Render Pipeline/Decal"); if ((Object)(object)val != (Object)null) { _decalBaseMaterial = new Material(val); } return _decalBaseMaterial; } public static Material FindSceneMaterial(string matName) { if (string.IsNullOrEmpty(matName)) { return null; } if (_materialCache.TryGetValue(matName, out var value) && (Object)(object)value != (Object)null) { return value; } foreach (MeshRenderer item in Object.FindObjectsOfType<MeshRenderer>()) { if ((Object)(object)item == (Object)null) { continue; } Il2CppReferenceArray<Material> sharedMaterials = ((Renderer)item).sharedMaterials; if (sharedMaterials == null) { continue; } foreach (Material item2 in (Il2CppArrayBase<Material>)(object)sharedMaterials) { if ((Object)(object)item2 != (Object)null && ((Object)item2).name == matName) { _materialCache[matName] = item2; return item2; } } } foreach (Material item3 in Resources.FindObjectsOfTypeAll<Material>()) { if ((Object)(object)item3 != (Object)null && ((Object)item3).name == matName) { _materialCache[matName] = item3; return item3; } } return null; } public static Texture FindSceneTexture(string texName) { if (string.IsNullOrEmpty(texName)) { return null; } if (_textureCache.TryGetValue(texName, out var value) && (Object)(object)value != (Object)null) { return value; } foreach (Texture2D item in Resources.FindObjectsOfTypeAll<Texture2D>()) { if ((Object)(object)item != (Object)null && ((Object)item).name == texName) { _textureCache[texName] = (Texture)(object)item; return (Texture)(object)item; } } return null; } private static Material CreateBakedMaterial(string textureName, float[] colorTint) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_007b: 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) Texture val = FindSceneTexture(textureName); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard")); if (val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", val); } val2.mainTexture = val; if (colorTint != null && colorTint.Length >= 4) { Color val3 = default(Color); ((Color)(ref val3))..ctor(colorTint[0], colorTint[1], colorTint[2], colorTint[3]); val2.color = val3; if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val3); } } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", 0f); } return val2; } private static Material CreateFallbackMaterial(MeshEntry entry) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard")); float[] array = entry.Color ?? DefaultColor; val.color = new Color(array[0], array[1], array[2], array[3]); if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", val.color); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } if (val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", 0.1f); } return val; } private static Material ApplyMaterialOverrides(Material mat, float[] colorTint, float? metallic, float? smoothness, float[] emissiveColor, float? emissiveIntensity, bool alreadyCloned = false) { //IL_0037: 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_0057: 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_006c: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mat == (Object)null) { return null; } if (colorTint == null && !metallic.HasValue && !smoothness.HasValue && emissiveColor == null && !emissiveIntensity.HasValue) { return mat; } Material val = (Material)(alreadyCloned ? ((object)mat) : ((object)new Material(mat))); if (colorTint != null && colorTint.Length >= 4) { Color val2 = (val.HasProperty("_BaseColor") ? val.GetColor("_BaseColor") : val.color); Color val3 = default(Color); ((Color)(ref val3))..ctor(val2.r * colorTint[0], val2.g * colorTint[1], val2.b * colorTint[2], val2.a * colorTint[3]); val.color = val3; if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", val3); } } if (metallic.HasValue && val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", metallic.Value); } if (smoothness.HasValue && val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", smoothness.Value); } if (emissiveColor != null && emissiveColor.Length >= 3) { if (!val.HasProperty("_EmissionColor")) { Shader val4 = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val4 != (Object)null) { val.shader = val4; } } if (val.HasProperty("_EmissionColor")) { float valueOrDefault = emissiveIntensity.GetValueOrDefault(1f); Color val5 = default(Color); ((Color)(ref val5))..ctor(emissiveColor[0] * valueOrDefault, emissiveColor[1] * valueOrDefault, emissiveColor[2] * valueOrDefault); val.EnableKeyword("_EMISSION"); val.SetColor("_EmissionColor", val5); val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)2; } } return val; } } }
Plugins/MeshVault.Mono.dll
Decompiled 3 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using MelonLoader; using MeshVault; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.Rendering.Universal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(MeshVaultPlugin), "MeshVault", "1.0.8", "hdlmrell", null)] [assembly: MelonColor(255, 100, 149, 237)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace MeshVault { public class MeshVaultPlugin : MelonPlugin { public override void OnPreInitialization() { } } internal static class JsonParser { internal static void ParseDatabase(string json, Dictionary<string, MeshEntry> db) { int pos = 0; int length = json.Length; SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != '{') { return; } pos++; while (pos < length) { SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] == '}') { break; } if (json[pos] == ',') { pos++; continue; } string text = ReadJsonString(json, ref pos, length); if (text == null) { break; } SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != ':') { break; } pos++; SkipWhitespace(json, ref pos, length); if (pos >= length || json[pos] != '{') { break; } int num = pos; int num2 = 1; pos++; while (pos < length && num2 > 0) { if (json[pos] == '{') { num2++; } else if (json[pos] == '}') { num2--; } if (num2 > 0) { pos++; } } if (pos >= length) { break; } pos++; string json2 = json.Substring(num, pos - num); MeshEntry meshEntry = ParseEntry(json2); if (meshEntry != null) { db[text] = meshEntry; } } } private static MeshEntry ParseEntry(string json) { MeshEntry meshEntry = new MeshEntry(); try { string json2 = json; int num = json.IndexOf("\"childMeshes\"", StringComparison.Ordinal); if (num >= 0) { json2 = json.Substring(0, num) + "}"; } meshEntry.Vertices = ParseVec3Array(ExtractArrayValue(json2, "vertices")); meshEntry.Normals = ParseVec3Array(ExtractArrayValue(json2, "normals")); meshEntry.UVs = ParseVec2Array(ExtractArrayValue(json2, "uvs")); meshEntry.Triangles = ParseIntArray(ExtractArrayValue(json2, "triangles")); meshEntry.MaterialName = ExtractStringValue(json2, "materialName") ?? "Standard"; meshEntry.ShaderName = ExtractStringValue(json2, "shaderName") ?? "Standard"; meshEntry.Color = ParseFloatArray(ExtractArrayValue(json2, "color")) ?? MeshVaultAPI.DefaultColor; meshEntry.BoundsCenter = ParseFloatArray(ExtractArrayValue(json2, "boundsCenter")) ?? new float[3]; meshEntry.BoundsSize = ParseFloatArray(ExtractArrayValue(json2, "boundsSize")) ?? new float[3] { 1f, 1f, 1f }; int[] array = ParseIntArray(ExtractArrayValue(json2, "subMeshTriCounts")); if (array != null && array.Length != 0) { meshEntry.SubMeshTriCounts = array; meshEntry.SubMeshMaterialNames = ParseStringArray(ExtractArrayValue(json2, "subMeshMaterialNames")); meshEntry.SubMeshShaderNames = ParseStringArray(ExtractArrayValue(json2, "subMeshShaderNames")); meshEntry.SubMeshTextureNames = ParseStringArray(ExtractArrayValue(json2, "subMeshTextureNames")); meshEntry.SubMeshColorTints = ParseFloat4ArrayOfArrays(ExtractArrayValue(json2, "subMeshColorTints")); } string text = ExtractStringValue(json2, "textureName"); meshEntry.TextureName = (string.IsNullOrEmpty(text) ? null : text); meshEntry.BakedColorTint = ParseFloatArray(ExtractArrayValue(json2, "bakedColorTint")); meshEntry.ColorTint = ParseFloatArray(ExtractArrayValue(json2, "colorTint")); meshEntry.Metallic = ExtractFloatValue(json2, "metallic"); meshEntry.Smoothness = ExtractFloatValue(json2, "smoothness"); meshEntry.EmissiveColor = ParseFloatArray(ExtractArrayValue(json2, "emissiveColor")); meshEntry.EmissiveIntensity = ExtractFloatValue(json2, "emissiveIntensity"); meshEntry.ChildMeshes = ParseChildMeshArray(json); return meshEntry; } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Warning("Parse entry failed: " + ex.Message); return null; } } internal static string ExtractArrayValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length || json[num] != '[') { return null; } int num2 = num; int num3 = 1; for (num++; num < json.Length; num++) { if (num3 <= 0) { break; } if (json[num] == '[') { num3++; } else if (json[num] == ']') { num3--; } } return json.Substring(num2, num - num2); } internal static string ExtractStringValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length || json[num] != '"') { return null; } int pos = num; return ReadJsonString(json, ref pos, json.Length); } internal static float? ExtractFloatValue(string json, string key) { string text = "\"" + key + "\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && (json[num] == ':' || json[num] == ' ' || json[num] == '\t'); num++) { } if (num >= json.Length) { return null; } int num2 = num; for (; num < json.Length && json[num] != ',' && json[num] != '}' && json[num] != '\n' && json[num] != '\r'; num++) { } string text2 = json.Substring(num2, num - num2).Trim(); if (string.IsNullOrEmpty(text2) || text2 == "null") { return null; } if (float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return null; } private static Vector3[] ParseVec3Array(string arrayStr) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(arrayStr)) { return (Vector3[])(object)new Vector3[0]; } List<Vector3> list = new List<Vector3>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string text = arrayStr.Substring(num2 + 1, num3 - num2 - 1); string[] array = text.Split(','); if (array.Length >= 3) { list.Add(new Vector3(float.Parse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[2], NumberStyles.Float, CultureInfo.InvariantCulture))); } num = num3 + 1; } return list.ToArray(); } private static Vector2[] ParseVec2Array(string arrayStr) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(arrayStr)) { return (Vector2[])(object)new Vector2[0]; } List<Vector2> list = new List<Vector2>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string text = arrayStr.Substring(num2 + 1, num3 - num2 - 1); string[] array = text.Split(','); if (array.Length >= 2) { list.Add(new Vector2(float.Parse(array[0], NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1], NumberStyles.Float, CultureInfo.InvariantCulture))); } num = num3 + 1; } return list.ToArray(); } private static int[] ParseIntArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return new int[0]; } arrayStr = arrayStr.Trim(); if (arrayStr.StartsWith("[")) { arrayStr = arrayStr.Substring(1); } if (arrayStr.EndsWith("]")) { arrayStr = arrayStr.Substring(0, arrayStr.Length - 1); } string[] array = arrayStr.Split(','); List<int> list = new List<int>(); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.Length > 0 && int.TryParse(text2, out var result)) { list.Add(result); } } return list.ToArray(); } private static float[] ParseFloatArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } arrayStr = arrayStr.Trim(); if (arrayStr.StartsWith("[")) { arrayStr = arrayStr.Substring(1); } if (arrayStr.EndsWith("]")) { arrayStr = arrayStr.Substring(0, arrayStr.Length - 1); } string[] array = arrayStr.Split(','); List<float> list = new List<float>(); string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (text2.Length > 0 && float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { list.Add(result); } } return list.ToArray(); } private static string[] ParseStringArray(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } List<string> list = new List<string>(); int i = 0; int length; for (length = arrayStr.Length; i < length && arrayStr[i] != '['; i++) { } if (i < length) { i++; } while (i < length) { SkipWhitespace(arrayStr, ref i, length); if (i >= length || arrayStr[i] == ']') { break; } if (arrayStr[i] == ',') { i++; continue; } string text = ReadJsonString(arrayStr, ref i, length); if (text != null) { list.Add(text); continue; } break; } return (list.Count > 0) ? list.ToArray() : null; } private static float[][] ParseFloat4ArrayOfArrays(string arrayStr) { if (string.IsNullOrEmpty(arrayStr)) { return null; } List<float[]> list = new List<float[]>(); int num = 1; int length = arrayStr.Length; while (num < length) { int num2 = arrayStr.IndexOf('[', num); if (num2 < 0) { break; } int num3 = arrayStr.IndexOf(']', num2); if (num3 < 0) { break; } string text = arrayStr.Substring(num2 + 1, num3 - num2 - 1); string[] array = text.Split(','); if (array.Length >= 4) { list.Add(new float[4] { float.Parse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture), float.Parse(array[3].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture) }); } num = num3 + 1; } return (list.Count > 0) ? list.ToArray() : null; } private static ChildMeshEntry[] ParseChildMeshArray(string json) { string text = "\"childMeshes\""; int num = json.IndexOf(text, StringComparison.Ordinal); if (num < 0) { return null; } for (num += text.Length; num < json.Length && json[num] != '['; num++) { } if (num >= json.Length) { return null; } int num2 = num; int num3 = 1; for (num++; num < json.Length; num++) { if (num3 <= 0) { break; } if (json[num] == '[') { num3++; } else if (json[num] == ']') { num3--; } } string text2 = json.Substring(num2 + 1, num - num2 - 2); List<ChildMeshEntry> list = new List<ChildMeshEntry>(); int num4 = 0; while (num4 < text2.Length) { int num5 = text2.IndexOf('{', num4); if (num5 < 0) { break; } int num6 = 1; int i; for (i = num5 + 1; i < text2.Length; i++) { if (num6 <= 0) { break; } if (text2[i] == '{') { num6++; } else if (text2[i] == '}') { num6--; } } string json2 = text2.Substring(num5, i - num5); try { ChildMeshEntry item = new ChildMeshEntry { Vertices = ParseVec3Array(ExtractArrayValue(json2, "vertices")), Normals = ParseVec3Array(ExtractArrayValue(json2, "normals")), UVs = ParseVec2Array(ExtractArrayValue(json2, "uvs")), Triangles = ParseIntArray(ExtractArrayValue(json2, "triangles")), MaterialName = (ExtractStringValue(json2, "materialName") ?? "Standard"), ShaderName = (ExtractStringValue(json2, "shaderName") ?? "Standard"), Color = (ParseFloatArray(ExtractArrayValue(json2, "color")) ?? MeshVaultAPI.DefaultColor), ColorTint = ParseFloatArray(ExtractArrayValue(json2, "colorTint")), Metallic = ExtractFloatValue(json2, "metallic"), Smoothness = ExtractFloatValue(json2, "smoothness"), EmissiveColor = ParseFloatArray(ExtractArrayValue(json2, "emissiveColor")), EmissiveIntensity = ExtractFloatValue(json2, "emissiveIntensity") }; list.Add(item); } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Warning("Parse child mesh failed: " + ex.Message); } num4 = i; } return (list.Count > 0) ? list.ToArray() : null; } private static void SkipWhitespace(string s, ref int pos, int len) { while (pos < len && (s[pos] == ' ' || s[pos] == '\t' || s[pos] == '\n' || s[pos] == '\r')) { pos++; } } private static string ReadJsonString(string s, ref int pos, int len) { SkipWhitespace(s, ref pos, len); if (pos >= len || s[pos] != '"') { return null; } pos++; StringBuilder stringBuilder = new StringBuilder(); while (pos < len) { char c = s[pos]; if (c == '\\' && pos + 1 < len) { pos++; stringBuilder.Append(s[pos]); } else { if (c == '"') { pos++; return stringBuilder.ToString(); } stringBuilder.Append(c); } pos++; } return stringBuilder.ToString(); } } public class ChildMeshEntry { public Vector3[] Vertices; public Vector3[] Normals; public Vector2[] UVs; public int[] Triangles; public string MaterialName; public string ShaderName; public float[] Color; public float[] ColorTint; public float? Metallic; public float? Smoothness; public float[] EmissiveColor; public float? EmissiveIntensity; } public class MeshEntry { public Vector3[] Vertices; public Vector3[] Normals; public Vector2[] UVs; public int[] Triangles; public string MaterialName; public string ShaderName; public float[] Color; public float[] BoundsCenter; public float[] BoundsSize; public int[] SubMeshTriCounts; public string[] SubMeshMaterialNames; public string[] SubMeshShaderNames; public string TextureName; public float[] BakedColorTint; public string[] SubMeshTextureNames; public float[][] SubMeshColorTints; public float[] ColorTint; public float? Metallic; public float? Smoothness; public float[] EmissiveColor; public float? EmissiveIntensity; public ChildMeshEntry[] ChildMeshes; } public static class MeshVaultAPI { private const string EmbeddedResourceName = "MeshVault.Resources.MeshDatabase.json"; private const string URPLitShader = "Universal Render Pipeline/Lit"; private const string URPSimpleLitShader = "Universal Render Pipeline/Simple Lit"; private const string StandardShader = "Standard"; private const string WorldspaceUVShaderTag = "WorldspaceUV"; private const string ShaderPropBaseMap = "_BaseMap"; private const string ShaderPropBaseColor = "_BaseColor"; private const string ShaderPropMetallic = "_Metallic"; private const string ShaderPropSmoothness = "_Smoothness"; private const float DefaultMetallic = 0f; private const float DefaultSmoothness = 0.1f; private const string ShaderPropEmissionColor = "_EmissionColor"; private const string ShaderKeywordEmission = "_EMISSION"; private const float BakedSmoothness = 0f; internal const string DecalPropBaseMap = "_Base_Map"; internal const string DecalPropColor = "_Color"; internal const float DecalDepth = 0.1f; private const string ApiLogPrefix = "[MeshVaultAPI]"; internal static readonly float[] DefaultColor = new float[4] { 1f, 1f, 1f, 1f }; private static Dictionary<string, MeshEntry> _cache; private static bool _loaded; private static readonly Dictionary<string, string> _registeredPrefixes = new Dictionary<string, string>(); private static readonly Dictionary<string, string> _registeredDecalPrefixes = new Dictionary<string, string>(); private static readonly Dictionary<string, Texture2D> _decalRegistry = new Dictionary<string, Texture2D>(); private static readonly Dictionary<string, Material> _materialCache = new Dictionary<string, Material>(); private static readonly Dictionary<string, Texture> _textureCache = new Dictionary<string, Texture>(); private static readonly HashSet<string> _materialBlacklist = new HashSet<string> { "SM_AC_Impostor", "filing cabinet mat", "mastermat1", "pallet rack mat", "pallet mat", "PolygonGangWarfare_Material_01_A", "PropsMat", "small bin mat", "rubbish bin mat" }; private static Material _decalBaseMaterial; private static string DiskPath => Path.Combine(Application.dataPath, "..", "UserData", "MeshVault", "MeshDatabase.json"); private static string DataDir => Path.Combine(Application.dataPath, "..", "UserData", "MeshVault"); public static void Init() { if (_loaded) { return; } _cache = new Dictionary<string, MeshEntry>(); try { string fullPath = Path.GetFullPath(DataDir); if (!Directory.Exists(fullPath)) { Directory.CreateDirectory(fullPath); } } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Error("Failed to create data directory: " + ex.Message); } string fullPath2 = Path.GetFullPath(DiskPath); if (File.Exists(fullPath2)) { try { string json = File.ReadAllText(fullPath2); JsonParser.ParseDatabase(json, _cache); Melon<MeshVaultPlugin>.Logger.Msg($"Loaded {_cache.Count} mesh entries from disk: {fullPath2}"); _loaded = true; return; } catch (Exception ex2) { Melon<MeshVaultPlugin>.Logger.Error("Failed to load from disk: " + ex2.Message); } } try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("MeshVault.Resources.MeshDatabase.json"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); string @string = Encoding.UTF8.GetString(array); JsonParser.ParseDatabase(@string, _cache); Melon<MeshVaultPlugin>.Logger.Msg($"Loaded {_cache.Count} mesh entries from embedded resource"); } else { Melon<MeshVaultPlugin>.Logger.Msg("No MeshDatabase.json found (disk or embedded) — starting with empty cache"); } } catch (Exception ex3) { Melon<MeshVaultPlugin>.Logger.Error("Failed to load from embedded resource: " + ex3.Message); } _loaded = true; } public static bool HasMesh(string id) { EnsureLoaded(); return _cache.ContainsKey(id); } public static MeshEntry GetMesh(string id) { EnsureLoaded(); MeshEntry value; return _cache.TryGetValue(id, out value) ? value : null; } public static string[] ListMeshes() { EnsureLoaded(); string[] array = new string[_cache.Count]; _cache.Keys.CopyTo(array, 0); return array; } public static Dictionary<string, MeshEntry> GetAllEntries() { EnsureLoaded(); return _cache; } public static Dictionary<string, float[]> BuildMaterialCatalog() { EnsureLoaded(); Dictionary<string, float[]> dictionary = new Dictionary<string, float[]>(); foreach (KeyValuePair<string, MeshEntry> item in _cache) { MeshEntry value = item.Value; if (!string.IsNullOrEmpty(value.MaterialName) && !dictionary.ContainsKey(value.MaterialName) && !_materialBlacklist.Contains(value.MaterialName)) { dictionary[value.MaterialName] = value.Color ?? DefaultColor; } if (value.SubMeshMaterialNames != null) { for (int i = 0; i < value.SubMeshMaterialNames.Length; i++) { string text = value.SubMeshMaterialNames[i]; if (!string.IsNullOrEmpty(text) && !dictionary.ContainsKey(text) && !_materialBlacklist.Contains(text)) { float[] value2 = ((value.SubMeshColorTints != null && i < value.SubMeshColorTints.Length && value.SubMeshColorTints[i] != null) ? value.SubMeshColorTints[i] : (value.Color ?? DefaultColor)); dictionary[text] = value2; } } } if (value.ChildMeshes == null) { continue; } ChildMeshEntry[] childMeshes = value.ChildMeshes; foreach (ChildMeshEntry childMeshEntry in childMeshes) { if (!string.IsNullOrEmpty(childMeshEntry.MaterialName) && !dictionary.ContainsKey(childMeshEntry.MaterialName) && !_materialBlacklist.Contains(childMeshEntry.MaterialName)) { dictionary[childMeshEntry.MaterialName] = childMeshEntry.Color ?? DefaultColor; } } } return dictionary; } public static void SetEntry(string id, MeshEntry entry) { EnsureLoaded(); _cache[id] = entry; } public static void InvalidateCache() { _cache = null; _loaded = false; _materialCache.Clear(); _textureCache.Clear(); } private static void EnsureLoaded() { if (!_loaded) { Init(); } } public static int RegisterMeshes(string prefix, string modName, string json) { EnsureLoaded(); if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(modName) || string.IsNullOrEmpty(json)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: prefix, modName, and json are required"); return -1; } foreach (char c in prefix) { if (!char.IsLetterOrDigit(c) || char.IsUpper(c)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: prefix \"" + prefix + "\" is invalid — must be lowercase alphanumeric only"); return -1; } } if (_registeredPrefixes.TryGetValue(prefix, out var value)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: prefix \"" + prefix + "\" is already claimed by \"" + value + "\""); return -1; } Dictionary<string, MeshEntry> dictionary = new Dictionary<string, MeshEntry>(); try { JsonParser.ParseDatabase(json, dictionary); } catch (Exception ex) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: failed to parse JSON from \"" + modName + "\": " + ex.Message); return -1; } if (dictionary.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterMeshes: JSON from \"" + modName + "\" contained no entries"); return 0; } string text = prefix + "_"; foreach (string key in dictionary.Keys) { if (!key.StartsWith(text)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterMeshes: entry \"" + key + "\" does not start with \"" + text + "\" — all entries from \"" + modName + "\" must use this prefix"); return -1; } } _registeredPrefixes[prefix] = modName; int num = 0; foreach (KeyValuePair<string, MeshEntry> item in dictionary) { if (_cache.ContainsKey(item.Key)) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterMeshes: entry \"" + item.Key + "\" already exists — skipping"); continue; } _cache[item.Key] = item.Value; num++; } Melon<MeshVaultPlugin>.Logger.Msg(string.Format("{0} Registered {1} mesh entries from \"{2}\" (prefix: \"{3}\")", "[MeshVaultAPI]", num, modName, prefix)); return num; } public static bool IsPrefixRegistered(string prefix) { return _registeredPrefixes.ContainsKey(prefix); } public static int RegisterDecals(string prefix, string modName, Dictionary<string, byte[]> textures) { //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Expected O, but got Unknown if (string.IsNullOrEmpty(prefix) || string.IsNullOrEmpty(modName) || textures == null) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: prefix, modName, and textures are required"); return -1; } foreach (char c in prefix) { if (!char.IsLetterOrDigit(c) || char.IsUpper(c)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: prefix \"" + prefix + "\" is invalid — must be lowercase alphanumeric only"); return -1; } } if (_registeredDecalPrefixes.TryGetValue(prefix, out var value)) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: prefix \"" + prefix + "\" is already claimed by \"" + value + "\""); return -1; } if (textures.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: no textures provided by \"" + modName + "\""); return 0; } _registeredDecalPrefixes[prefix] = modName; int num = 0; string text = prefix + "_"; foreach (KeyValuePair<string, byte[]> texture in textures) { string text2 = (texture.Key.StartsWith(text) ? texture.Key : (text + texture.Key)); if (_decalRegistry.ContainsKey(text2)) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: decal \"" + text2 + "\" already exists — skipping"); continue; } byte[] value2 = texture.Value; if (value2 == null || value2.Length == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: decal \"" + text2 + "\" has empty data — skipping"); continue; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val, value2)) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: failed to load image data for \"" + text2 + "\""); Object.Destroy((Object)(object)val); continue; } ((Object)val).name = text2; ((Texture)val).filterMode = (FilterMode)1; _decalRegistry[text2] = val; num++; } if (num == 0) { _registeredDecalPrefixes.Remove(prefix); } Melon<MeshVaultPlugin>.Logger.Msg(string.Format("{0} Registered {1} decal(s) from \"{2}\" (prefix: \"{3}\")", "[MeshVaultAPI]", num, modName, prefix)); return num; } public static int RegisterDecals(string prefix, string modName, Assembly assembly, string resourcePrefix = null) { if (assembly == null) { Melon<MeshVaultPlugin>.Logger.Error("[MeshVaultAPI] RegisterDecals: assembly is required"); return -1; } Dictionary<string, byte[]> dictionary = new Dictionary<string, byte[]>(); string[] manifestResourceNames = assembly.GetManifestResourceNames(); foreach (string text in manifestResourceNames) { if (resourcePrefix != null && !text.StartsWith(resourcePrefix)) { continue; } string text2 = text.ToLowerInvariant(); if (!text2.EndsWith(".png") && !text2.EndsWith(".jpg") && !text2.EndsWith(".jpeg")) { continue; } string text3 = text; if (resourcePrefix != null && text3.StartsWith(resourcePrefix)) { text3 = text3.Substring(resourcePrefix.Length); } int num = text3.LastIndexOf('.'); if (num > 0) { text3 = text3.Substring(0, num); } using Stream stream = assembly.GetManifestResourceStream(text); if (stream != null) { using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); dictionary[text3] = memoryStream.ToArray(); } } if (dictionary.Count == 0) { Melon<MeshVaultPlugin>.Logger.Warning("[MeshVaultAPI] RegisterDecals: no image resources found in assembly \"" + assembly.GetName().Name + "\"" + ((resourcePrefix != null) ? (" with prefix \"" + resourcePrefix + "\"") : "")); return 0; } return RegisterDecals(prefix, modName, dictionary); } public static string[] ListRegisteredDecals() { string[] array = new string[_decalRegistry.Count]; _decalRegistry.Keys.CopyTo(array, 0); return array; } public static Texture2D GetRegisteredDecal(string id) { Texture2D value; return _decalRegistry.TryGetValue(id, out value) ? value : null; } public static bool IsDecalPrefixRegistered(string prefix) { return _registeredDecalPrefixes.ContainsKey(prefix); } internal static bool RegisterDecalDirect(string id, Texture2D tex) { if (string.IsNullOrEmpty(id) || (Object)(object)tex == (Object)null) { return false; } if (_decalRegistry.ContainsKey(id)) { return false; } _decalRegistry[id] = tex; return true; } public static GameObject Spawn(string id, Vector3 position, Quaternion rotation, Transform parent = null, string namePrefix = "MeshVault", string[] materialOverrides = null, Color?[] colorOverrides = null) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_03b8: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Expected O, but got Unknown //IL_03f7: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_0476: Expected O, but got Unknown //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Expected O, but got Unknown //IL_0731: Unknown result type (might be due to invalid IL or missing references) //IL_0737: Expected O, but got Unknown //IL_0745: Unknown result type (might be due to invalid IL or missing references) //IL_0778: Unknown result type (might be due to invalid IL or missing references) //IL_084b: Unknown result type (might be due to invalid IL or missing references) //IL_0852: Expected O, but got Unknown //IL_085d: Unknown result type (might be due to invalid IL or missing references) //IL_05de: Unknown result type (might be due to invalid IL or missing references) //IL_05e5: Expected O, but got Unknown //IL_088a: Unknown result type (might be due to invalid IL or missing references) //IL_0609: Unknown result type (might be due to invalid IL or missing references) //IL_062f: Unknown result type (might be due to invalid IL or missing references) MeshEntry mesh = GetMesh(id); if (mesh == null) { Melon<MeshVaultPlugin>.Logger.Warning("Entry \"" + id + "\" not found"); return null; } Mesh val = new Mesh(); ((Object)val).name = "MV_" + id; val.vertices = mesh.Vertices; val.normals = mesh.Normals; val.uv = mesh.UVs; Material[] array2; if (mesh.SubMeshTriCounts != null && mesh.SubMeshTriCounts.Length != 0) { int num2 = (val.subMeshCount = mesh.SubMeshTriCounts.Length); int num3 = 0; for (int i = 0; i < num2; i++) { int num4 = mesh.SubMeshTriCounts[i]; int[] array = new int[num4]; Array.Copy(mesh.Triangles, num3, array, 0, num4); val.SetTriangles(array, i); num3 += num4; } array2 = (Material[])(object)new Material[num2]; for (int j = 0; j < num2; j++) { Material val2 = null; bool alreadyCloned = false; if (materialOverrides != null && j < materialOverrides.Length && materialOverrides[j] != null) { val2 = FindSceneMaterial(materialOverrides[j]); } if ((Object)(object)val2 == (Object)null) { string text = ((mesh.SubMeshShaderNames != null && j < mesh.SubMeshShaderNames.Length) ? mesh.SubMeshShaderNames[j] : ""); if (text.Contains("WorldspaceUV")) { string text2 = ((mesh.SubMeshTextureNames != null && j < mesh.SubMeshTextureNames.Length && !string.IsNullOrEmpty(mesh.SubMeshTextureNames[j])) ? mesh.SubMeshTextureNames[j] : mesh.TextureName); float[] colorTint = ((mesh.SubMeshColorTints != null && j < mesh.SubMeshColorTints.Length && mesh.SubMeshColorTints[j] != null) ? mesh.SubMeshColorTints[j] : mesh.BakedColorTint); if (!string.IsNullOrEmpty(text2)) { val2 = CreateBakedMaterial(text2, colorTint); alreadyCloned = (Object)(object)val2 != (Object)null; } } } if ((Object)(object)val2 == (Object)null) { string matName = ((mesh.SubMeshMaterialNames != null && j < mesh.SubMeshMaterialNames.Length) ? mesh.SubMeshMaterialNames[j] : mesh.MaterialName); val2 = FindSceneMaterial(matName); if ((Object)(object)val2 == (Object)null) { val2 = CreateFallbackMaterial(mesh); alreadyCloned = true; } } array2[j] = ApplyMaterialOverrides(val2, mesh.ColorTint, mesh.Metallic, mesh.Smoothness, mesh.EmissiveColor, mesh.EmissiveIntensity, alreadyCloned); } } else { val.triangles = mesh.Triangles; Material val3 = null; bool alreadyCloned2 = false; if (materialOverrides != null && materialOverrides.Length != 0 && materialOverrides[0] != null) { val3 = FindSceneMaterial(materialOverrides[0]); } if ((Object)(object)val3 == (Object)null && !string.IsNullOrEmpty(mesh.TextureName)) { val3 = CreateBakedMaterial(mesh.TextureName, mesh.BakedColorTint); alreadyCloned2 = (Object)(object)val3 != (Object)null; } if ((Object)(object)val3 == (Object)null) { val3 = FindSceneMaterial(mesh.MaterialName); if ((Object)(object)val3 == (Object)null) { val3 = CreateFallbackMaterial(mesh); alreadyCloned2 = true; } } array2 = (Material[])(object)new Material[1] { ApplyMaterialOverrides(val3, mesh.ColorTint, mesh.Metallic, mesh.Smoothness, mesh.EmissiveColor, mesh.EmissiveIntensity, alreadyCloned2) }; } val.RecalculateBounds(); GameObject val4 = new GameObject(namePrefix + "_" + id); MeshFilter val5 = val4.AddComponent<MeshFilter>(); val5.sharedMesh = val; MeshRenderer val6 = val4.AddComponent<MeshRenderer>(); ((Renderer)val6).sharedMaterials = array2; MeshCollider val7 = val4.AddComponent<MeshCollider>(); val7.sharedMesh = val; val4.transform.position = position; val4.transform.rotation = rotation; if ((Object)(object)parent != (Object)null) { val4.transform.SetParent(parent, true); } if (mesh.ChildMeshes != null) { for (int k = 0; k < mesh.ChildMeshes.Length; k++) { ChildMeshEntry childMeshEntry = mesh.ChildMeshes[k]; if (childMeshEntry.Vertices == null || childMeshEntry.Vertices.Length == 0) { continue; } Mesh val8 = new Mesh(); ((Object)val8).name = $"MV_{id}_child{k}"; val8.vertices = childMeshEntry.Vertices; val8.normals = childMeshEntry.Normals; val8.uv = childMeshEntry.UVs; val8.triangles = childMeshEntry.Triangles; val8.RecalculateBounds(); GameObject val9 = new GameObject($"child_{k}"); val9.transform.SetParent(val4.transform, false); MeshFilter val10 = val9.AddComponent<MeshFilter>(); val10.sharedMesh = val8; MeshCollider val11 = val9.AddComponent<MeshCollider>(); val11.sharedMesh = val8; MeshRenderer val12 = val9.AddComponent<MeshRenderer>(); int num5 = ((mesh.SubMeshTriCounts != null && mesh.SubMeshTriCounts.Length != 0) ? (mesh.SubMeshTriCounts.Length + k) : (1 + k)); Material val13 = null; if (materialOverrides != null && num5 < materialOverrides.Length && materialOverrides[num5] != null) { val13 = FindSceneMaterial(materialOverrides[num5]); } bool alreadyCloned3 = false; Material val14; if ((Object)(object)val13 != (Object)null) { val14 = val13; } else { Material val15 = FindSceneMaterial(childMeshEntry.MaterialName); if (val15 != null) { val14 = val15; } else { Shader val16 = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Standard"); val14 = new Material(val16); float[] array3 = childMeshEntry.Color ?? DefaultColor; val14.color = new Color(array3[0], array3[1], array3[2], array3[3]); if (val14.HasProperty("_BaseColor")) { val14.SetColor("_BaseColor", val14.color); } if (val14.HasProperty("_Metallic")) { val14.SetFloat("_Metallic", 0f); } if (val14.HasProperty("_Smoothness")) { val14.SetFloat("_Smoothness", 0.1f); } alreadyCloned3 = true; } } ((Renderer)val12).sharedMaterial = ApplyMaterialOverrides(val14, childMeshEntry.ColorTint, childMeshEntry.Metallic, childMeshEntry.Smoothness, childMeshEntry.EmissiveColor, childMeshEntry.EmissiveIntensity, alreadyCloned3); } } if (colorOverrides != null) { MeshRenderer component = val4.GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null) { Material[] sharedMaterials = ((Renderer)component).sharedMaterials; for (int l = 0; l < sharedMaterials.Length && l < colorOverrides.Length; l++) { if (colorOverrides[l].HasValue) { sharedMaterials[l] = new Material(sharedMaterials[l]); sharedMaterials[l].color = colorOverrides[l].Value; if (sharedMaterials[l].HasProperty("_BaseColor")) { sharedMaterials[l].SetColor("_BaseColor", colorOverrides[l].Value); } } } ((Renderer)component).sharedMaterials = sharedMaterials; } int num6 = ((mesh.SubMeshTriCounts == null || mesh.SubMeshTriCounts.Length == 0) ? 1 : mesh.SubMeshTriCounts.Length); if (mesh.ChildMeshes != null) { for (int m = 0; m < mesh.ChildMeshes.Length; m++) { int num7 = num6 + m; if (num7 >= colorOverrides.Length || !colorOverrides[num7].HasValue) { continue; } Transform child = val4.transform.GetChild(m); MeshRenderer val17 = ((child != null) ? ((Component)child).GetComponent<MeshRenderer>() : null); if (!((Object)(object)val17 == (Object)null)) { Material val18 = new Material(((Renderer)val17).sharedMaterial); val18.color = colorOverrides[num7].Value; if (val18.HasProperty("_BaseColor")) { val18.SetColor("_BaseColor", colorOverrides[num7].Value); } ((Renderer)val17).sharedMaterial = val18; } } } } return val4; } public static GameObject SpawnDecal(string textureName, Vector3 position, Quaternion rotation, Color? tintColor = null, Vector3? scale = null, Transform parent = null) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) Texture2D val = (Texture2D)(((object)GetRegisteredDecal(textureName)) ?? ((object)/*isinst with value type is only supported in some contexts*/)); if ((Object)(object)val == (Object)null) { Melon<MeshVaultPlugin>.Logger.Warning("Decal texture \"" + textureName + "\" not found"); return null; } Material val2 = FindDecalBaseMaterial(); if ((Object)(object)val2 == (Object)null) { Melon<MeshVaultPlugin>.Logger.Warning("No decal shader found in scene"); return null; } GameObject val3 = new GameObject("MV_Decal_" + textureName); DecalProjector val4 = val3.AddComponent<DecalProjector>(); Material val5 = new Material(val2); val5.SetTexture("_Base_Map", (Texture)(object)val); val5.SetColor("_Color", (Color)(((??)tintColor) ?? Color.white)); if (val5.HasProperty("_Normal_Map")) { val5.SetTexture("_Normal_Map", (Texture)null); } if (val5.HasProperty("_NormalMap")) { val5.SetTexture("_NormalMap", (Texture)null); } if (val5.HasProperty("_BumpMap")) { val5.SetTexture("_BumpMap", (Texture)null); } val4.material = val5; Vector3 val6 = (Vector3)(((??)scale) ?? Vector3.one); val4.size = new Vector3(val6.x, val6.y, 0.1f); val4.pivot = new Vector3(0f, 0f, 0.05f); val4.fadeFactor = 1f; val4.renderingLayerMask = uint.MaxValue; val3.transform.position = position; val3.transform.rotation = rotation; if ((Object)(object)parent != (Object)null) { val3.transform.SetParent(parent, true); } return val3; } private static Material FindDecalBaseMaterial() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown if ((Object)(object)_decalBaseMaterial != (Object)null) { return _decalBaseMaterial; } DecalProjector[] array = Object.FindObjectsOfType<DecalProjector>(true); DecalProjector[] array2 = array; foreach (DecalProjector val in array2) { if ((Object)(object)val != (Object)null && (Object)(object)val.material != (Object)null && (Object)(object)val.material.shader != (Object)null) { _decalBaseMaterial = new Material(val.material); return _decalBaseMaterial; } } Shader val2 = Shader.Find("Shader Graphs/Decal") ?? Shader.Find("Universal Render Pipeline/Decal"); if ((Object)(object)val2 != (Object)null) { _decalBaseMaterial = new Material(val2); } return _decalBaseMaterial; } public static Material FindSceneMaterial(string matName) { if (string.IsNullOrEmpty(matName)) { return null; } if (_materialCache.TryGetValue(matName, out var value) && (Object)(object)value != (Object)null) { return value; } MeshRenderer[] array = Object.FindObjectsOfType<MeshRenderer>(); MeshRenderer[] array2 = array; foreach (MeshRenderer val in array2) { if ((Object)(object)val == (Object)null) { continue; } Material[] sharedMaterials = ((Renderer)val).sharedMaterials; if (sharedMaterials == null) { continue; } Material[] array3 = sharedMaterials; foreach (Material val2 in array3) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name == matName) { _materialCache[matName] = val2; return val2; } } } Material[] array4 = Resources.FindObjectsOfTypeAll<Material>(); Material[] array5 = array4; foreach (Material val3 in array5) { if ((Object)(object)val3 != (Object)null && ((Object)val3).name == matName) { _materialCache[matName] = val3; return val3; } } return null; } public static Texture FindSceneTexture(string texName) { if (string.IsNullOrEmpty(texName)) { return null; } if (_textureCache.TryGetValue(texName, out var value) && (Object)(object)value != (Object)null) { return value; } Texture2D[] array = Resources.FindObjectsOfTypeAll<Texture2D>(); Texture2D[] array2 = array; foreach (Texture2D val in array2) { if ((Object)(object)val != (Object)null && ((Object)val).name == texName) { _textureCache[texName] = (Texture)(object)val; return (Texture)(object)val; } } return null; } private static Material CreateBakedMaterial(string textureName, float[] colorTint) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Texture val = FindSceneTexture(textureName); if ((Object)(object)val == (Object)null) { return null; } Shader val2 = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard"); Material val3 = new Material(val2); if (val3.HasProperty("_BaseMap")) { val3.SetTexture("_BaseMap", val); } val3.mainTexture = val; if (colorTint != null && colorTint.Length >= 4) { Color val4 = default(Color); ((Color)(ref val4))..ctor(colorTint[0], colorTint[1], colorTint[2], colorTint[3]); val3.color = val4; if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", val4); } } if (val3.HasProperty("_Metallic")) { val3.SetFloat("_Metallic", 0f); } if (val3.HasProperty("_Smoothness")) { val3.SetFloat("_Smoothness", 0f); } return val3; } private static Material CreateFallbackMaterial(MeshEntry entry) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_004c: 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) Shader val = Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Universal Render Pipeline/Simple Lit") ?? Shader.Find("Standard"); Material val2 = new Material(val); float[] array = entry.Color ?? DefaultColor; val2.color = new Color(array[0], array[1], array[2], array[3]); if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", val2.color); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", 0.1f); } return val2; } private static Material ApplyMaterialOverrides(Material mat, float[] colorTint, float? metallic, float? smoothness, float[] emissiveColor, float? emissiveIntensity, bool alreadyCloned = false) { //IL_004d: 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_007a: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)mat == (Object)null) { return null; } if (colorTint == null && !metallic.HasValue && !smoothness.HasValue && emissiveColor == null && !emissiveIntensity.HasValue) { return mat; } Material val = (Material)(alreadyCloned ? ((object)mat) : ((object)new Material(mat))); if (colorTint != null && colorTint.Length >= 4) { Color val2 = (val.HasProperty("_BaseColor") ? val.GetColor("_BaseColor") : val.color); Color val3 = default(Color); ((Color)(ref val3))..ctor(val2.r * colorTint[0], val2.g * colorTint[1], val2.b * colorTint[2], val2.a * colorTint[3]); val.color = val3; if (val.HasProperty("_BaseColor")) { val.SetColor("_BaseColor", val3); } } if (metallic.HasValue && val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", metallic.Value); } if (smoothness.HasValue && val.HasProperty("_Smoothness")) { val.SetFloat("_Smoothness", smoothness.Value); } if (emissiveColor != null && emissiveColor.Length >= 3) { if (!val.HasProperty("_EmissionColor")) { Shader val4 = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val4 != (Object)null) { val.shader = val4; } } if (val.HasProperty("_EmissionColor")) { float valueOrDefault = emissiveIntensity.GetValueOrDefault(1f); Color val5 = default(Color); ((Color)(ref val5))..ctor(emissiveColor[0] * valueOrDefault, emissiveColor[1] * valueOrDefault, emissiveColor[2] * valueOrDefault); val.EnableKeyword("_EMISSION"); val.SetColor("_EmissionColor", val5); val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)2; } } return val; } } }