Decompiled source of MeshVault v1.0.9

Plugins/MeshVault.Il2Cpp.dll

Decompiled 3 days ago
using 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 ago
using 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;
		}
	}
}