Decompiled source of Custom Car Mod v1.1.4

Distance.CustomCar.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Distance.CustomCar.Data.Car;
using Distance.CustomCar.Data.Errors;
using Distance.CustomCar.Data.Materials;
using Events;
using Events.Car;
using Events.MainMenu;
using HarmonyLib;
using JsonFx.Json;
using JsonFx.Model;
using JsonFx.Serialization;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Distance.ModTemplate")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Distance.ModTemplate")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("7bcb2908-b003-45d9-be68-50cba5217603")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
public static class DictionaryExtensions
{
	public static bool ContainsKey<T>(this Dictionary<string, object> obj, string key)
	{
		try
		{
			obj.GetItem<T>(key);
			return true;
		}
		catch
		{
			return false;
		}
	}

	public static T GetItem<T>(this Dictionary<string, object> obj, string key)
	{
		if (!obj.ContainsKey(key))
		{
			throw new KeyNotFoundException("The key requested doesn't exist in store: '" + key + "'.");
		}
		try
		{
			return (T)Convert.ChangeType(obj[key], typeof(T));
		}
		catch (Exception innerException)
		{
			throw new Exception("Failed type conversion exception has been thrown.", innerException);
		}
	}

	public static T GetOrCreate<T>(this Dictionary<string, object> obj, string key) where T : new()
	{
		if (!obj.ContainsKey(key))
		{
			obj[key] = new T();
		}
		return obj.GetItem<T>(key);
	}

	public static T GetOrCreate<T>(this Dictionary<string, object> obj, string key, T defaultValue)
	{
		if (!obj.ContainsKey<T>(key))
		{
			obj[key] = defaultValue;
		}
		return obj.GetItem<T>(key);
	}

	public static T GetOrCreate<T>(this Dictionary<string, object> obj, string key, Func<T> factory) where T : class
	{
		if (!obj.ContainsKey(key))
		{
			return (T)(obj[key] = factory());
		}
		return (T)obj[key];
	}
}
public static class GameObjectExtensions
{
	public static string FullName(this GameObject obj)
	{
		if (!Object.op_Implicit((Object)(object)obj.transform.parent))
		{
			return ((Object)obj).name;
		}
		return ((Component)obj.transform.parent).gameObject.FullName() + "/" + ((Object)obj).name;
	}
}
namespace Distance.CustomCar
{
	public class Assets
	{
		private string _filePath = null;

		private string RootDirectory { get; }

		private string FileName { get; set; }

		private string FilePath => _filePath ?? Path.Combine(Path.Combine(RootDirectory, "Assets"), FileName);

		public object Bundle { get; private set; }

		private Assets()
		{
		}

		public Assets(string fileName)
		{
			RootDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
			FileName = fileName;
			if (!File.Exists(FilePath))
			{
				Mod.Log.LogError((object)("Couldn't find requested asset bundle at " + FilePath));
			}
			else
			{
				Bundle = Load();
			}
		}

		public static Assets FromUnsafePath(string filePath)
		{
			if (!File.Exists(filePath))
			{
				Mod.Log.LogError((object)("Could not find requested asset bundle at " + filePath));
				return null;
			}
			Assets assets = new Assets
			{
				_filePath = filePath,
				FileName = Path.GetFileName(filePath)
			};
			assets.Bundle = assets.Load();
			if (assets.Bundle == null)
			{
				return null;
			}
			return assets;
		}

		private object Load()
		{
			try
			{
				return AssetBundleBridge.LoadFrom(FilePath);
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)ex);
				return null;
			}
		}
	}
	internal static class AssetBundleBridge
	{
		private static Type _assetBundleType;

		private static MethodInfo _loadFromFile;

		public static Type AssetBundleType => _assetBundleType;

		private static MethodInfo LoadFromFile => _loadFromFile;

		static AssetBundleBridge()
		{
			_assetBundleType = Kernel.FindTypeByFullName("UnityEngine.AssetBundle", "UnityEngine");
			_loadFromFile = _assetBundleType.GetMethod("LoadFromFile", new Type[1] { typeof(string) });
		}

		public static object LoadFrom(string path)
		{
			MethodInfo loadFromFile = LoadFromFile;
			object[] parameters = new string[1] { path };
			return loadFromFile.Invoke(null, parameters);
		}
	}
	internal static class Kernel
	{
		internal static Type FindTypeByFullName(string fullName, string assemblyFilter)
		{
			IEnumerable<Assembly> enumerable = from a in AppDomain.CurrentDomain.GetAssemblies()
				where a.GetName().Name.Contains(assemblyFilter)
				select a;
			foreach (Assembly item in enumerable)
			{
				Type type = item.GetTypes().FirstOrDefault((Type t) => t.FullName == fullName);
				if ((object)type == null)
				{
					continue;
				}
				return type;
			}
			Mod.Log.LogError((object)("Type " + fullName + " wasn't found in the main AppDomain at this moment."));
			throw new Exception("Type " + fullName + " wasn't found in the main AppDomain at this moment.");
		}
	}
	public class FileSystem
	{
		public string RootDirectory { get; }

		public string VirtualFileSystemRoot => Path.Combine(RootDirectory, "Data");

		public FileSystem()
		{
			RootDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
			if (!Directory.Exists(VirtualFileSystemRoot))
			{
				Directory.CreateDirectory(VirtualFileSystemRoot);
			}
		}

		public bool FileExists(string path)
		{
			string path2 = Path.Combine(VirtualFileSystemRoot, path);
			return File.Exists(path2);
		}

		public bool DirectoryExists(string path)
		{
			string path2 = Path.Combine(VirtualFileSystemRoot, path);
			return Directory.Exists(path2);
		}

		public bool PathExists(string path)
		{
			return FileExists(path) || DirectoryExists(path);
		}

		public byte[] ReadAllBytes(string filePath)
		{
			string text = Path.Combine(VirtualFileSystemRoot, filePath);
			if (!File.Exists(text))
			{
				Mod.Log.LogInfo((object)("Couldn't read a file for path '" + text + "'. File does not exist."));
				return null;
			}
			return File.ReadAllBytes(text);
		}

		public FileStream CreateFile(string filePath, bool overwrite = false)
		{
			string text = Path.Combine(VirtualFileSystemRoot, filePath);
			if (File.Exists(text))
			{
				if (!overwrite)
				{
					Mod.Log.LogInfo((object)("Couldn't create a mod VFS file for path '" + text + "'. The file already exists."));
					return null;
				}
				Mod.Log.LogInfo((object)("Couldn't delete a mod VFS file for path '" + text + "'. File does not exist."));
				RemoveFile(filePath);
			}
			try
			{
				return File.Create(text);
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Couldn't create a mod VFS file for path '" + text + "'."));
				Mod.Log.LogInfo((object)ex);
				return null;
			}
		}

		public void RemoveFile(string filePath)
		{
			string text = Path.Combine(VirtualFileSystemRoot, filePath);
			if (!File.Exists(text))
			{
				Mod.Log.LogInfo((object)("Couldn't delete a mod VFS file for path '" + text + "'. File does not exist."));
				return;
			}
			try
			{
				File.Delete(text);
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Couldn't delete a mod VFS file for path '" + text + "'."));
				Mod.Log.LogInfo((object)ex);
			}
		}

		public void IterateOver(string directoryPath, Action<string, bool> action, bool sort = true)
		{
			string text = Path.Combine(VirtualFileSystemRoot, directoryPath);
			if (!Directory.Exists(text))
			{
				Mod.Log.LogInfo((object)("Cannot iterate over directory at '" + text + "'. It doesn't exist."));
				return;
			}
			List<string> list = Directory.GetFiles(text).ToList();
			list.AddRange(Directory.GetDirectories(text));
			if (sort)
			{
				list = list.OrderBy((string x) => x).ToList();
			}
			foreach (string item in list)
			{
				try
				{
					bool arg = Directory.Exists(item);
					action(item, arg);
				}
				catch (Exception ex)
				{
					Mod.Log.LogInfo((object)("Action for the element at path '" + item + "' failed. See file system exception log for details."));
					Mod.Log.LogInfo((object)ex);
					break;
				}
			}
		}

		public List<string> GetDirectories(string directoryPath, string searchPattern)
		{
			string text = Path.Combine(VirtualFileSystemRoot, directoryPath);
			if (!Directory.Exists(text))
			{
				Mod.Log.LogInfo((object)("Cannot get directories in directory at '" + text + "'. It doesn't exist."));
				return null;
			}
			return Directory.GetDirectories(text, searchPattern).ToList();
		}

		public List<string> GetDirectories(string directoryPath)
		{
			return GetDirectories(directoryPath, "*");
		}

		public List<string> GetFiles(string directoryPath, string searchPattern)
		{
			string text = Path.Combine(VirtualFileSystemRoot, directoryPath);
			if (!Directory.Exists(text))
			{
				Mod.Log.LogInfo((object)("Cannot get files in directory at '" + text + "'. It doesn't exist."));
				return null;
			}
			return Directory.GetFiles(text, searchPattern).ToList();
		}

		public List<string> GetFiles(string directoryPath)
		{
			return GetFiles(directoryPath, "*");
		}

		public FileStream OpenFile(string filePath, FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
		{
			string text = Path.Combine(VirtualFileSystemRoot, filePath);
			if (!File.Exists(text))
			{
				Mod.Log.LogInfo((object)("Couldn't open a VFS file. The requested file: '" + text + "' does not exist."));
				return null;
			}
			try
			{
				return File.Open(text, fileMode, fileAccess, fileShare);
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Couldn't open a VFS file for path '" + text + "'."));
				Mod.Log.LogInfo((object)ex);
				return null;
			}
		}

		public FileStream OpenFile(string filePath)
		{
			return OpenFile(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
		}

		public string CreateDirectory(string directoryName)
		{
			string text = Path.Combine(VirtualFileSystemRoot, directoryName);
			try
			{
				Directory.CreateDirectory(text);
				return text;
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Couldn't create a VFS directory for path '" + text + "'."));
				Mod.Log.LogInfo((object)ex);
				return string.Empty;
			}
		}

		public void RemoveDirectory(string directoryPath)
		{
			string text = Path.Combine(VirtualFileSystemRoot, directoryPath);
			if (!Directory.Exists(text))
			{
				Mod.Log.LogInfo((object)("Couldn't remove a VFS directory for path '" + text + "'. Directory does not exist."));
				return;
			}
			try
			{
				Directory.Delete(text, recursive: true);
			}
			catch (Exception ex)
			{
				Mod.Log.LogInfo((object)("Couldn't remove a VFS directory for path '" + text + "'."));
				Mod.Log.LogInfo((object)ex);
			}
		}

		public static string GetValidFileName(string dirtyFileName, string replaceInvalidCharsWith = "_")
		{
			return Regex.Replace(dirtyFileName, "[^\\w\\s\\.]", replaceInvalidCharsWith, RegexOptions.None);
		}

		public static string GetValidFileNameToLower(string dirtyFileName, string replaceInvalidCharsWith = "_")
		{
			return GetValidFileName(dirtyFileName, replaceInvalidCharsWith).ToLower();
		}
	}
	public sealed class MessageBox
	{
		private readonly string Message = "";

		private readonly string Title = "";

		private float Time = 0f;

		private ButtonType Buttons = (ButtonType)0;

		private Action Confirm;

		private Action Cancel;

		private MessageBox(string message, string title)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Message = message;
			Title = title;
			Confirm = EmptyAction;
			Cancel = EmptyAction;
		}

		public static MessageBox Create(string content, string title = "")
		{
			return new MessageBox(content, title);
		}

		public MessageBox SetButtons(MessageButtons buttons)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			Buttons = (ButtonType)buttons;
			return this;
		}

		public MessageBox SetTimeout(float delay)
		{
			Time = delay;
			return this;
		}

		public MessageBox OnConfirm(Action action)
		{
			Confirm = action;
			return this;
		}

		public MessageBox OnCancel(Action action)
		{
			Cancel = action;
			return this;
		}

		public void Show()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0042: Expected O, but got Unknown
			G.Sys.MenuPanelManager_.ShowMessage(Message, Title, (OnButtonClicked)delegate
			{
				Confirm();
			}, (OnButtonClicked)delegate
			{
				Cancel();
			}, Buttons, false, (Pivot)4, Time);
		}

		private void EmptyAction()
		{
		}
	}
	[Flags]
	public enum MessageButtons
	{
		Ok = 0,
		OkCancel = 1,
		YesNo = 2
	}
	[BepInPlugin("Distance.CustomCar", "Custom Car", "1.1.4")]
	public sealed class Mod : BaseUnityPlugin
	{
		private const string modGUID = "Distance.CustomCar";

		private const string modName = "Custom Car";

		private const string modVersion = "1.1.4";

		public static string UseTrumpetKey = "Use Trumpet Horn";

		private static readonly Harmony harmony = new Harmony("Distance.CustomCar");

		public static ManualLogSource Log = new ManualLogSource("Custom Car");

		public static Mod Instance;

		private bool displayErrors_ = true;

		public static ConfigEntry<bool> UseTrumpetHorn { get; set; }

		public static int DefaultCarCount { get; private set; }

		public static int ModdedCarCount => TotalCarCount - DefaultCarCount;

		public static int TotalCarCount { get; private set; }

		public ErrorList Errors { get; set; }

		public ProfileCarColors CarColors { get; set; }

		private void Awake()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Expected O, but got Unknown
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			Log = Logger.CreateLogSource("Distance.CustomCar");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Thanks for using Custom Cars!");
			Errors = new ErrorList(((BaseUnityPlugin)this).Logger);
			CarColors = ((Component)this).gameObject.AddComponent<ProfileCarColors>();
			UseTrumpetHorn = ((BaseUnityPlugin)this).Config.Bind<bool>("General", UseTrumpetKey, false, new ConfigDescription("Custom car models will use the encryptor horn (the \"doot!\" trumpet).", (AcceptableValueBase)null, new object[0]));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading...");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loaded!");
		}

		public void Start()
		{
			ProfileManager profileManager_ = G.Sys.ProfileManager_;
			DefaultCarCount = profileManager_.CarInfos_.Length;
			CarInfos carInfos = new CarInfos();
			carInfos.CollectInfos();
			CarBuilder carBuilder = new CarBuilder();
			carBuilder.CreateCars(carInfos);
			TotalCarCount = profileManager_.CarInfos_.Length;
			CarColors.LoadAll();
			Errors.Show();
		}

		private void OnEnable()
		{
			StaticEvent<Data>.Subscribe((Delegate<Data>)OnMainMenuLoaded);
		}

		private void OnDisable()
		{
			StaticEvent<Data>.Unsubscribe((Delegate<Data>)OnMainMenuLoaded);
		}

		private void OnMainMenuLoaded(Data _)
		{
			if (displayErrors_)
			{
				Errors.Show();
				displayErrors_ = false;
			}
		}

		private void OnConfigChanged(object sender, EventArgs e)
		{
			SettingChangedEventArgs e2 = (SettingChangedEventArgs)(object)((e is SettingChangedEventArgs) ? e : null);
			if (e2 != null)
			{
			}
		}
	}
	public class ProfileCarColors : MonoBehaviour
	{
		internal Settings Config;

		public event Action<ProfileCarColors> OnChanged;

		protected void Load()
		{
			Config = new Settings("CustomCars");
		}

		protected void Awake()
		{
			Load();
			Save();
		}

		protected Dictionary<string, object> Profile(string profileName)
		{
			return Config.GetOrCreate(profileName, () => new Dictionary<string, object>());
		}

		protected Dictionary<string, object> Vehicle(string profileName, string vehicleName)
		{
			return Profile(profileName).GetOrCreate(vehicleName, () => new Dictionary<string, object>());
		}

		protected CarColors GetCarColors(string profileName, string vehicleName)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, object> vehicle = Vehicle(profileName, vehicleName);
			CarColors val = new CarColors
			{
				primary_ = GetColor(vehicle, "primary", Colors.whiteSmoke),
				secondary_ = GetColor(vehicle, "secondary", Colors.darkGray),
				glow_ = GetColor(vehicle, "glow", Colors.cyan),
				sparkle_ = GetColor(vehicle, "sparkle", Colors.lightSlateGray)
			};
			SetCarColors(profileName, vehicleName, val);
			return val;
		}

		protected Color GetColor(Dictionary<string, object> vehicle, string category, Color defaultColor)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, object> orCreate = vehicle.GetOrCreate(category, () => new Dictionary<string, object>());
			float orCreate2 = orCreate.GetOrCreate("r", defaultColor.r);
			float orCreate3 = orCreate.GetOrCreate("g", defaultColor.g);
			float orCreate4 = orCreate.GetOrCreate("b", defaultColor.b);
			float orCreate5 = orCreate.GetOrCreate("a", defaultColor.a);
			return new Color(orCreate2, orCreate3, orCreate4, orCreate5);
		}

		protected void SetCarColors(string profileName, string vehicleName, CarColors colors)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, object> dictionary = Vehicle(profileName, vehicleName);
			dictionary["primary"] = ToSection(colors.primary_);
			dictionary["secondary"] = ToSection(colors.secondary_);
			dictionary["glow"] = ToSection(colors.glow_);
			dictionary["sparkle"] = ToSection(colors.sparkle_);
			Dictionary<string, object> dictionary2 = Profile(profileName);
			dictionary2[vehicleName] = dictionary;
			Config[profileName] = dictionary2;
		}

		protected Section ToSection(Color color)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			return new Section
			{
				["r"] = color.r,
				["g"] = color.g,
				["b"] = color.b,
				["a"] = color.a
			};
		}

		protected void Save()
		{
			Config.Save();
			this.OnChanged?.Invoke(this);
		}

		public void LoadAll()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			ProfileManager profileManager_ = G.Sys.ProfileManager_;
			List<Profile> profiles_ = profileManager_.profiles_;
			foreach (Profile item in profiles_)
			{
				CarColors[] array = (CarColors[])(object)new CarColors[Mod.TotalCarCount];
				for (int i = 0; i < profileManager_.CarInfos_.Length; i++)
				{
					if (i < Mod.DefaultCarCount)
					{
						array[i] = item.carColorsList_[i];
						continue;
					}
					CarInfo val = profileManager_.CarInfos_[i];
					Mod.Log.LogInfo((object)("Getting car color in " + item.FileName_ + "'s profile for the " + val.name_ + " car"));
					CarColors carColors = GetCarColors(item.FileName_, val.name_);
					array[i] = carColors;
				}
				item.carColorsList_ = array;
			}
		}

		public void SaveAll()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			ProfileManager profileManager_ = G.Sys.ProfileManager_;
			List<Profile> profiles_ = profileManager_.profiles_;
			foreach (Profile item in profiles_)
			{
				for (int i = 0; i < profileManager_.CarInfos_.Length; i++)
				{
					if (i >= Mod.DefaultCarCount)
					{
						CarInfo val = profileManager_.CarInfos_[i];
						CarColors colors = item.carColorsList_[i];
						SetCarColors(item.FileName_, val.name_, colors);
					}
				}
			}
			Save();
		}
	}
	public class Section : Dictionary<string, object>
	{
		public new object this[string key]
		{
			get
			{
				if (!ContainsKey(key))
				{
					return null;
				}
				return base[key];
			}
			set
			{
				if (!ContainsKey(key))
				{
					Add(key, value);
					this.ValueChanged?.Invoke(this, new SettingsChangedEventArgs(key, null, base[key]));
				}
				else
				{
					object oldValue = base[key];
					base[key] = value;
					this.ValueChanged?.Invoke(this, new SettingsChangedEventArgs(key, oldValue, base[key]));
				}
			}
		}

		public event EventHandler<SettingsChangedEventArgs> ValueChanged;

		public T GetItem<T>(string key)
		{
			if (!ContainsKey(key))
			{
				Mod.Log.LogError((object)("The key requested doesn't exist in store: '" + key + "'."));
				throw new KeyNotFoundException("The key requested doesn't exist in store: '" + key + "'.");
			}
			try
			{
				return (T)Convert.ChangeType(this[key], typeof(T));
			}
			catch (Exception ex)
			{
				Mod.Log.LogWarning((object)$"Failed type conversion exception has been thrown. String: {key} \n{ex}");
				throw new SettingsException("Failed type conversion exception has been thrown.", key, isJsonFailure: false, ex);
			}
		}

		public T GetOrCreate<T>(string key) where T : new()
		{
			if (!ContainsKey(key))
			{
				this[key] = new T();
				this.ValueChanged?.Invoke(this, new SettingsChangedEventArgs(key, null, this[key]));
			}
			return GetItem<T>(key);
		}

		public T GetOrCreate<T>(string key, T defaultValue)
		{
			if (!ContainsKey<T>(key))
			{
				this[key] = defaultValue;
				this.ValueChanged?.Invoke(this, new SettingsChangedEventArgs(key, null, this[key]));
			}
			return GetItem<T>(key);
		}

		public T GetOrCreate<T>(string key, Func<T> factory) where T : class
		{
			if (!ContainsKey(key))
			{
				T result = (T)(this[key] = factory());
				this.ValueChanged?.Invoke(this, new SettingsChangedEventArgs(key, null, this[key]));
				return result;
			}
			return (T)this[key];
		}

		public bool ContainsKey<T>(string key)
		{
			try
			{
				GetItem<T>(key);
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	public class Settings : Section
	{
		private string FileName { get; }

		private string RootDirectory { get; }

		private string SettingsDirectory => Path.Combine(RootDirectory, "Settings");

		private string FilePath => Path.Combine(SettingsDirectory, FileName);

		public Settings(string fileName)
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			RootDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
			FileName = fileName + ".json";
			Mod.Log.LogInfo((object)("Settings instance for '" + FilePath + "' initializing..."));
			if (!File.Exists(FilePath))
			{
				return;
			}
			bool flag = false;
			using (StreamReader streamReader = new StreamReader(FilePath))
			{
				string text = streamReader.ReadToEnd();
				JsonReader val = new JsonReader();
				Section section = null;
				try
				{
					section = ((DataReader<ModelTokenType>)(object)val).Read<Section>(text);
				}
				catch (Exception ex)
				{
					Mod.Log.LogWarning((object)ex);
					flag = true;
				}
				if (section != null)
				{
					foreach (string key in section.Keys)
					{
						Add(key, section[key]);
					}
				}
			}
			if (flag)
			{
				Save();
			}
		}

		public void Save(bool formatJson = true)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (!Directory.Exists(SettingsDirectory))
			{
				Directory.CreateDirectory(SettingsDirectory);
			}
			DataWriterSettings val = new DataWriterSettings
			{
				PrettyPrint = formatJson
			};
			JsonWriter val2 = new JsonWriter(val);
			try
			{
				using StreamWriter streamWriter = new StreamWriter(FilePath, append: false);
				streamWriter.WriteLine(((DataWriter<ModelTokenType>)(object)val2).Write((object)this));
			}
			catch (Exception ex)
			{
				Mod.Log.LogWarning((object)ex);
			}
		}
	}
	public class SettingsChangedEventArgs : EventArgs
	{
		public string Key { get; }

		public object OldValue { get; }

		public object NewValue { get; }

		public SettingsChangedEventArgs(string key, object oldValue = null, object newValue = null)
		{
			Key = key;
			OldValue = oldValue;
			NewValue = newValue;
		}
	}
	public class SettingsException : Exception
	{
		public string Key { get; }

		public bool IsJsonFailure { get; }

		public SettingsException(string message, string key, bool isJsonFailure, Exception innerException)
			: base(message, innerException)
		{
			Key = key;
			IsJsonFailure = isJsonFailure;
		}

		public SettingsException(string message, string key, bool isJsonFailure)
			: this(message, key, isJsonFailure, null)
		{
		}
	}
}
namespace Distance.CustomCar.Patches
{
	[HarmonyPatch(typeof(CarAudio), "OnCarHornEvent")]
	internal static class OnCarHornEvent
	{
		[HarmonyPrefix]
		internal static bool Prefix(CarAudio __instance, Data data)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			int num = G.Sys.ProfileManager_.knownCars_[__instance.carLogic_.PlayerData_.CarName_];
			if (num >= Mod.DefaultCarCount && Mod.UseTrumpetHorn.Value)
			{
				__instance.phantom_.SetRTPCValue("Horn_volume", Mathf.Clamp01(data.hornPercent_ + 0.5f));
				__instance.phantom_.Play("SpookyHorn", 0f, true);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(GadgetWithAnimation), "SetAnimationStateValues")]
	internal static class GadgetWithAnimation__SetAnimationStateValues
	{
		[HarmonyPrefix]
		internal static bool Prefix(GadgetWithAnimation __instance)
		{
			Animation componentInChildren = ((Component)__instance).GetComponentInChildren<Animation>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				return PatchAnimations(componentInChildren, __instance.animationName_);
			}
			return false;
		}

		private static bool PatchAnimations(Animation animation, string name)
		{
			if (Object.op_Implicit((Object)(object)animation))
			{
				if (!ChangeBlendModeToBlend(((Component)animation).transform, name))
				{
					return true;
				}
				AnimationState val = animation[name];
				if (TrackedReference.op_Implicit((TrackedReference)(object)val))
				{
					val.layer = 3;
					val.blendMode = (AnimationBlendMode)0;
					val.wrapMode = (WrapMode)8;
					val.enabled = true;
					val.weight = 1f;
					val.speed = 0f;
				}
			}
			return false;
		}

		private static bool ChangeBlendModeToBlend(Transform obj, string animationName)
		{
			for (int i = 0; i < obj.childCount; i++)
			{
				string text = ((Object)((Component)obj.GetChild(i)).gameObject).name.ToLower();
				if (!text.StartsWith("#"))
				{
					continue;
				}
				text = text.Remove(0, 1);
				string[] array = text.Split(new char[1] { ';' });
				if (array.Length == 1)
				{
					if (array[0] == "additive")
					{
						return false;
					}
					if (array[0] == "blend")
					{
						return true;
					}
				}
				if (array[1] == animationName.ToLower())
				{
					if (array[0] == "additive")
					{
						return false;
					}
					if (array[0] == "blend")
					{
						return true;
					}
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Profile), "Awake")]
	internal static class Profile__Awake
	{
		[HarmonyPostfix]
		internal static void Postfix(Profile __instance)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			CarColors[] array = (CarColors[])(object)new CarColors[G.Sys.ProfileManager_.carInfos_.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = G.Sys.ProfileManager_.carInfos_[i].colors_;
			}
			__instance.carColorsList_ = array;
		}
	}
	[HarmonyPatch(typeof(Profile), "Save")]
	internal static class Profile__Save
	{
		[HarmonyPostfix]
		internal static void Postfix()
		{
			Mod.Instance.CarColors.SaveAll();
		}
	}
	[HarmonyPatch(typeof(Profile), "SetColorsForAllCars", new Type[] { typeof(CarColors) })]
	internal static class Profile__SetColorsForAllCars
	{
		[HarmonyPrefix]
		internal static bool Prefix(Profile __instance, CarColors cc)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			CarColors[] array = (CarColors[])(object)new CarColors[G.Sys.ProfileManager_.carInfos_.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = cc;
			}
			__instance.carColorsList_ = array;
			__instance.dataModified_ = true;
			return false;
		}
	}
}
namespace Distance.CustomCar.Data.Materials
{
	public class MaterialInfos
	{
		public Material material;

		public int diffuseIndex = -1;

		public int normalIndex = -1;

		public int emitIndex = -1;

		public void ReplaceMaterialInRenderer(Renderer renderer, int materialIndex)
		{
			if (!((Object)(object)material == (Object)null) && !((Object)(object)renderer == (Object)null) && materialIndex < renderer.materials.Length)
			{
				ref Material reference = ref renderer.materials[materialIndex];
				Material val = Object.Instantiate<Material>(material);
				if (diffuseIndex >= 0)
				{
					val.SetTexture(diffuseIndex, reference.GetTexture("_MainTex"));
				}
				if (emitIndex >= 0)
				{
					val.SetTexture(emitIndex, reference.GetTexture("_EmissionMap"));
				}
				if (normalIndex >= 0)
				{
					val.SetTexture(normalIndex, reference.GetTexture("_BumpMap"));
				}
				renderer.materials[materialIndex] = val;
			}
		}
	}
	public class MaterialPropertyExport
	{
		public string fromName;

		public string toName;

		public int fromID = -1;

		public int toID = -1;

		public PropertyType type;
	}
	public class MaterialPropertyInfo
	{
		public string shaderName;

		public string name;

		public int diffuseIndex = -1;

		public int normalIndex = -1;

		public int emitIndex = -1;

		public MaterialPropertyInfo(string _shaderName, string _name, int _diffuseIndex, int _normalIndex, int _emitIndex)
		{
			shaderName = _shaderName;
			name = _name;
			diffuseIndex = _diffuseIndex;
			normalIndex = _normalIndex;
			emitIndex = _emitIndex;
		}
	}
	public enum PropertyType
	{
		Color,
		ColorArray,
		Float,
		FloatArray,
		Int,
		Matrix,
		MatrixArray,
		Texture,
		Vector,
		VectorArray
	}
}
namespace Distance.CustomCar.Data.Errors
{
	public class ErrorList : List<string>
	{
		private readonly ManualLogSource logger_;

		public ErrorList(ManualLogSource logger)
		{
			logger_ = logger;
		}

		public new void Add(string value)
		{
			base.Add(value);
			logger_.LogInfo((object)value);
		}

		public void Add(Exception value)
		{
			base.Add(value.ToString());
			logger_.LogInfo((object)value);
		}

		public void Show()
		{
			if (this.Any())
			{
				string arg = ((base.Count < 15) ? string.Join(Environment.NewLine, ToArray()) : "There were too many errors when loading custom cars to be displayed here, please check the logs in your mod installation directory.");
				MessageBox.Create($"Can't load the cars correctly: {base.Count} error(s)\n{arg}", "CUSTOM CARS - ERRORS").SetButtons(MessageButtons.Ok).Show();
			}
		}
	}
}
namespace Distance.CustomCar.Data.Car
{
	public class CarBuilder
	{
		private struct BundleLoadResult
		{
			public string FilePath;

			public AssetBundle Bundle;

			public Exception Error;
		}

		private CarInfos infos_;

		public void CreateCars(CarInfos infos)
		{
			infos_ = infos;
			Dictionary<string, GameObject> dictionary = LoadAssetsBundles();
			List<CreateCarReturnInfos> list = new List<CreateCarReturnInfos>();
			foreach (KeyValuePair<string, GameObject> item in dictionary)
			{
				try
				{
					Mod.Log.LogInfo((object)("Creating car prefab for " + item.Key + " ..."));
					CreateCarReturnInfos createCarReturnInfos = CreateCar(item.Value);
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item.Key.Substring(0, item.Key.LastIndexOf('(') - 1));
					((Object)createCarReturnInfos.car).name = fileNameWithoutExtension;
					list.Add(createCarReturnInfos);
				}
				catch (Exception value)
				{
					Mod.Log.LogError((object)("Could not load car prefab: " + item.Key));
					Mod.Instance.Errors.Add("Could not load car prefab: " + item.Key);
					Mod.Instance.Errors.Add(value);
				}
			}
			RegisterCars(list);
		}

		private void RegisterCars(List<CreateCarReturnInfos> carsInfos)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0281: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			Mod.Log.LogInfo((object)$"Registering {carsInfos.Count} car(s)...");
			ProfileManager profileManager_ = G.Sys.ProfileManager_;
			CarInfo[] array = ICollectionEx.ToArray<CarInfo>((ICollection<CarInfo>)profileManager_.carInfos_);
			profileManager_.carInfos_ = (CarInfo[])(object)new CarInfo[array.Length + carsInfos.Count];
			ref Dictionary<string, int> unlockedCars_ = ref profileManager_.unlockedCars_;
			ref Dictionary<string, int> knownCars_ = ref profileManager_.knownCars_;
			for (int i = 0; i < profileManager_.carInfos_.Length; i++)
			{
				if (i < array.Length)
				{
					profileManager_.carInfos_[i] = array[i];
					continue;
				}
				int index = i - array.Length;
				CarInfo val = new CarInfo
				{
					name_ = ((Object)carsInfos[index].car).name,
					prefabs_ = new CarPrefabs
					{
						carPrefab_ = carsInfos[index].car
					},
					colors_ = carsInfos[index].colors
				};
				if (!knownCars_.ContainsKey(val.name_) && !unlockedCars_.ContainsKey(val.name_))
				{
					unlockedCars_.Add(val.name_, i);
					knownCars_.Add(val.name_, i);
				}
				else
				{
					Mod.Instance.Errors.Add("A car with the name " + val.name_ + " is already registered, rename the car file if they're the same.");
					Mod.Log.LogInfo((object)("Generating unique name for car " + val.name_));
					string text = $"#{Guid.NewGuid():B}";
					Mod.Log.LogInfo((object)("Using GUID: " + text));
					val.name_ = "[FFFF00]![-] " + val.name_ + " " + text;
					unlockedCars_.Add(val.name_, i);
					knownCars_.Add(val.name_, i);
				}
				profileManager_.carInfos_[i] = val;
			}
			CarColors[] array2 = (CarColors[])(object)new CarColors[array.Length + carsInfos.Count];
			for (int j = 0; j < array2.Length; j++)
			{
				array2[j] = G.Sys.ProfileManager_.carInfos_[j].colors_;
			}
			for (int k = 0; k < profileManager_.ProfileCount_; k++)
			{
				Profile profile = profileManager_.GetProfile(k);
				CarColors[] carColorsList_ = profile.carColorsList_;
				for (int l = 0; l < carColorsList_.Length && l < array2.Length; l++)
				{
					array2[l] = carColorsList_[l];
				}
				profile.carColorsList_ = array2;
			}
		}

		private Dictionary<string, GameObject> LoadAssetsBundles()
		{
			Dictionary<string, GameObject> dictionary = new Dictionary<string, GameObject>();
			DirectoryInfo directoryInfo = new DirectoryInfo(Path.Combine(Resource.personalDistanceDirPath_, "CustomCars"));
			if (!directoryInfo.Exists)
			{
				try
				{
					directoryInfo.Create();
				}
				catch (Exception ex)
				{
					Mod.Instance.Errors.Add("Could not create the following folder: " + directoryInfo.FullName);
					Mod.Log.LogError((object)("Could not create the following folder: " + directoryInfo.FullName));
					Mod.Instance.Errors.Add(ex);
					Mod.Log.LogError((object)ex);
				}
			}
			PrefabIndex prefabIndex = new PrefabIndex();
			prefabIndex.Load();
			DirectoryInfo directoryInfo2 = new DirectoryInfo(Directory.GetParent(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location)).ToString());
			List<FileInfo> list = new List<FileInfo>();
			foreach (FileInfo item in from x in ArrayEx.Concat<FileInfo>(directoryInfo2.GetFiles("*", SearchOption.AllDirectories), directoryInfo.GetFiles("*", SearchOption.AllDirectories))
				orderby x.Name
				select x)
			{
				if (item.Extension == "" && HasValidBundleSignature(item.FullName))
				{
					list.Add(item);
				}
			}
			List<FileInfo> list2 = list;
			HashSet<string> hashSet = new HashSet<string>();
			int num = Math.Max(4, Environment.ProcessorCount);
			int num2 = (list2.Count + num - 1) / num;
			for (int num3 = 0; num3 < list2.Count; num3 += num)
			{
				int num4 = Math.Min(num3 + num, list2.Count);
				Mod.Log.LogInfo((object)$"Batch {num3 / num + 1}/{num2} ({num4 - num3} files)");
				BundleLoadResult[] batchResults = new BundleLoadResult[num4 - num3];
				int batchCount = batchResults.Length;
				int loaded = 0;
				ManualResetEvent batchDone = new ManualResetEvent(initialState: false);
				try
				{
					for (int num5 = 0; num5 < batchCount; num5++)
					{
						int index = num5;
						FileInfo file = list2[num3 + num5];
						ThreadPool.QueueUserWorkItem(delegate
						{
							batchResults[index] = LoadBundle(file);
							if (Interlocked.Increment(ref loaded) == batchCount)
							{
								batchDone.Set();
							}
						});
					}
					if (!batchDone.WaitOne(30000))
					{
						Mod.Log.LogWarning((object)$"Bundle batch {num3 / num + 1} timed out after 30s — incomplete results will be skipped.");
						for (int num6 = 0; num6 < batchCount; num6++)
						{
							if (batchResults[num6].FilePath == null)
							{
								batchResults[num6] = new BundleLoadResult
								{
									FilePath = list2[num3 + num6].FullName,
									Error = new TimeoutException("Bundle loading timed out after 30 seconds — the file may be corrupted")
								};
							}
						}
					}
				}
				finally
				{
					if (batchDone != null)
					{
						((IDisposable)batchDone).Dispose();
					}
				}
				BundleLoadResult[] array = batchResults;
				for (int num7 = 0; num7 < array.Length; num7++)
				{
					BundleLoadResult bundleLoadResult = array[num7];
					string filePath = bundleLoadResult.FilePath;
					hashSet.Add(filePath);
					if ((Object)(object)bundleLoadResult.Bundle == (Object)null)
					{
						Mod.Instance.Errors.Add("Could not load assets file: " + filePath);
						Mod.Log.LogError((object)("Could not load assets file: " + filePath));
						if (bundleLoadResult.Error != null)
						{
							Mod.Instance.Errors.Add(bundleLoadResult.Error);
							Mod.Log.LogError((object)bundleLoadResult.Error);
						}
						continue;
					}
					AssetBundle bundle = bundleLoadResult.Bundle;
					string[] array2;
					if (prefabIndex.IsUpToDate(filePath))
					{
						array2 = prefabIndex.GetPrefabNames(filePath);
						if (array2 == null || array2.Length == 0)
						{
							array2 = ScanBundleForPrefabs(bundle);
						}
					}
					else
					{
						array2 = ScanBundleForPrefabs(bundle);
						if (array2.Length != 0)
						{
							Mod.Log.LogInfo((object)$"Scanned: {Path.GetFileName(filePath)} ({array2.Length} prefab(s))");
						}
					}
					prefabIndex.SetPrefabNames(filePath, array2);
					int num8 = 0;
					string[] array3 = array2;
					foreach (string text in array3)
					{
						GameObject value = bundle.LoadAsset<GameObject>(text);
						string key = filePath + " (" + text + ")";
						if (!dictionary.ContainsKey(key))
						{
							dictionary.Add(key, value);
							num8++;
						}
					}
					if (num8 == 0)
					{
						Mod.Instance.Errors.Add("Can't find a prefab in the asset bundle: " + filePath);
						Mod.Log.LogError((object)("Can't find a prefab in the asset bundle: " + filePath));
					}
					bundle.Unload(false);
				}
			}
			Mod.Log.LogInfo((object)$"{dictionary.Count} prefab(s) loaded from {hashSet.Count} file(s)");
			prefabIndex.RemoveStaleEntries(hashSet);
			prefabIndex.Save();
			return dictionary;
		}

		private static bool HasValidBundleSignature(string filePath)
		{
			try
			{
				using FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
				if (fileStream.Length < 8)
				{
					return false;
				}
				byte[] array = new byte[8];
				if (fileStream.Read(array, 0, 8) != 8)
				{
					return false;
				}
				if (array[0] == 85 && array[1] == 110 && array[2] == 105 && array[3] == 116 && array[4] == 121 && array[5] == 70 && array[6] == 83)
				{
					return true;
				}
				if (array[0] == 85 && array[1] == 110 && array[2] == 105 && array[3] == 116 && array[4] == 121 && array[5] == 82 && array[6] == 97 && array[7] == 119)
				{
					return true;
				}
				if (array[0] == 85 && array[1] == 110 && array[2] == 105 && array[3] == 116 && array[4] == 121 && array[5] == 87 && array[6] == 101 && array[7] == 98)
				{
					return true;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		private static BundleLoadResult LoadBundle(FileInfo file)
		{
			try
			{
				if (!HasValidBundleSignature(file.FullName))
				{
					return new BundleLoadResult
					{
						FilePath = file.FullName,
						Error = new InvalidDataException("File is not a valid Unity AssetBundle (missing UnityFS/UnityRaw/UnityWeb header)")
					};
				}
				Assets assets = Assets.FromUnsafePath(file.FullName);
				if (assets == null)
				{
					return new BundleLoadResult
					{
						FilePath = file.FullName
					};
				}
				return new BundleLoadResult
				{
					FilePath = file.FullName,
					Bundle = (AssetBundle)/*isinst with value type is only supported in some contexts*/
				};
			}
			catch (Exception error)
			{
				return new BundleLoadResult
				{
					FilePath = file.FullName,
					Error = error
				};
			}
		}

		private static string[] ScanBundleForPrefabs(AssetBundle bundle)
		{
			List<string> list = new List<string>();
			string[] allAssetNames = bundle.GetAllAssetNames();
			foreach (string text in allAssetNames)
			{
				if (text.EndsWith(".prefab", StringComparison.InvariantCultureIgnoreCase))
				{
					list.Add(text);
				}
			}
			return list.ToArray();
		}

		private CreateCarReturnInfos CreateCar(GameObject car)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			CreateCarReturnInfos createCarReturnInfos = new CreateCarReturnInfos();
			GameObject val = Object.Instantiate<GameObject>(infos_.baseCar);
			((Object)val).name = ((Object)car).name;
			Object.DontDestroyOnLoad((Object)(object)val);
			val.SetActive(false);
			RemoveOldCar(val);
			GameObject car2 = AddNewCarOnPrefab(val, car);
			SetCarDatas(val, car2);
			createCarReturnInfos.car = val;
			createCarReturnInfos.colors = LoadDefaultColors(car2);
			return createCarReturnInfos;
		}

		private void RemoveOldCar(GameObject obj)
		{
			List<GameObject> list = new List<GameObject>();
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)obj.transform.GetChild(i)).gameObject;
				if (((Object)gameObject).name.IndexOf("wheel", StringComparison.InvariantCultureIgnoreCase) >= 0)
				{
					list.Add(gameObject);
				}
			}
			if (list.Count != 4)
			{
				Mod.Instance.Errors.Add($"Found {list.Count} wheels on base prefabs, expected 4");
				Mod.Log.LogError((object)$"Found {list.Count} wheels on base prefabs, expected 4");
			}
			Transform val = obj.transform.Find("Refractor");
			if ((Object)(object)val == (Object)null)
			{
				Mod.Instance.Errors.Add("Can't find the Refractor object on the base car prefab");
				Mod.Log.LogError((object)"Can't find the Refractor object on the base car prefab");
				return;
			}
			Object.Destroy((Object)(object)((Component)val).gameObject);
			foreach (GameObject item in list)
			{
				Object.Destroy((Object)(object)item);
			}
		}

		private GameObject AddNewCarOnPrefab(GameObject obj, GameObject car)
		{
			return Object.Instantiate<GameObject>(car, obj.transform);
		}

		private void SetCarDatas(GameObject obj, GameObject car)
		{
			SetColorChanger(obj.GetComponent<ColorChanger>(), car);
			SetCarVisuals(obj.GetComponent<CarVisuals>(), car);
		}

		private void SetColorChanger(ColorChanger colorChanger, GameObject car)
		{
			if ((Object)(object)colorChanger == (Object)null)
			{
				Mod.Instance.Errors.Add("Can't find the ColorChanger component on the base car");
				Mod.Log.LogError((object)"Can't find the ColorChanger component on the base car");
				return;
			}
			colorChanger.rendererChangers_ = (RendererChanger[])(object)new RendererChanger[0];
			Renderer[] componentsInChildren = car.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				ReplaceMaterials(val);
				if ((Object)(object)colorChanger != (Object)null)
				{
					AddMaterialColorChanger(colorChanger, ((Component)val).transform);
				}
			}
		}

		private void ReplaceMaterials(Renderer renderer)
		{
			string[] array = new string[renderer.materials.Length];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = "wheel";
			}
			List<MaterialPropertyExport>[] array2 = new List<MaterialPropertyExport>[renderer.materials.Length];
			for (int j = 0; j < array2.Length; j++)
			{
				array2[j] = new List<MaterialPropertyExport>();
			}
			FillMaterialInfos(renderer, array, array2);
			Material[] materials = renderer.materials;
			Material[] array3 = (Material[])(object)new Material[materials.Length];
			Array.Copy(materials, array3, materials.Length);
			for (int k = 0; k < materials.Length; k++)
			{
				if (!infos_.materials.TryGetValue(array[k], out var value))
				{
					Mod.Instance.Errors.Add("Can't find the material " + array[k] + " on " + ((Component)renderer).gameObject.FullName());
					Mod.Log.LogError((object)("Can't find the material " + array[k] + " on " + ((Component)renderer).gameObject.FullName()));
				}
				else
				{
					if (value == null || (Object)(object)value.material == (Object)null)
					{
						continue;
					}
					Material val = Object.Instantiate<Material>(value.material);
					if (value.diffuseIndex >= 0)
					{
						val.SetTexture(value.diffuseIndex, materials[k].GetTexture("_MainTex"));
					}
					if (value.normalIndex >= 0)
					{
						val.SetTexture(value.normalIndex, materials[k].GetTexture("_BumpMap"));
					}
					if (value.emitIndex >= 0)
					{
						val.SetTexture(value.emitIndex, materials[k].GetTexture("_EmissionMap"));
					}
					foreach (MaterialPropertyExport item in array2[k])
					{
						CopyMaterialProperty(materials[k], val, item);
					}
					array3[k] = val;
				}
			}
			renderer.materials = array3;
		}

		private void FillMaterialInfos(Renderer renderer, string[] matNames, List<MaterialPropertyExport>[] materialProperties)
		{
			int childCount = ((Component)renderer).transform.childCount;
			for (int i = 0; i < childCount; i++)
			{
				string text = ((Object)((Component)renderer).transform.GetChild(i)).name.ToLower();
				if (!text.StartsWith("#"))
				{
					continue;
				}
				text = text.Remove(0, 1);
				string[] array = text.Split(new char[1] { ';' });
				if (array.Length == 0)
				{
					continue;
				}
				if (array[0].Contains("mat"))
				{
					int result;
					if (array.Length != 3)
					{
						Mod.Instance.Errors.Add(array[0] + " property on " + ((Component)renderer).gameObject.FullName() + " must have 2 arguments");
						Mod.Log.LogError((object)(array[0] + " property on " + ((Component)renderer).gameObject.FullName() + " must have 2 arguments"));
					}
					else if (!int.TryParse(array[1], out result))
					{
						Mod.Instance.Errors.Add("First argument of " + array[0] + " on " + ((Component)renderer).gameObject.FullName() + " property must be a number");
						Mod.Log.LogError((object)("First argument of " + array[0] + " on " + ((Component)renderer).gameObject.FullName() + " property must be a number"));
					}
					else if (result < matNames.Length)
					{
						matNames[result] = array[2];
					}
				}
				else
				{
					if (!array[0].Contains("export"))
					{
						continue;
					}
					int result2;
					if (array.Length != 5)
					{
						Mod.Instance.Errors.Add(array[0] + " property on " + ((Component)renderer).gameObject.FullName() + " must have 4 arguments");
						Mod.Log.LogError((object)(array[0] + " property on " + ((Component)renderer).gameObject.FullName() + " must have 4 arguments"));
					}
					else if (!int.TryParse(array[1], out result2))
					{
						Mod.Instance.Errors.Add("First argument of " + array[0] + " on " + ((Component)renderer).gameObject.FullName() + " property must be a number");
						Mod.Log.LogError((object)("First argument of " + array[0] + " on " + ((Component)renderer).gameObject.FullName() + " property must be a number"));
					}
					else
					{
						if (result2 >= matNames.Length)
						{
							continue;
						}
						MaterialPropertyExport materialPropertyExport = new MaterialPropertyExport();
						bool flag = false;
						foreach (PropertyType value in Enum.GetValues(typeof(PropertyType)))
						{
							if (array[2] == value.ToString().ToLower())
							{
								flag = true;
								materialPropertyExport.type = value;
								break;
							}
						}
						if (!flag)
						{
							Mod.Instance.Errors.Add("The property " + array[2] + " on " + ((Component)renderer).gameObject.FullName() + " is not valid");
							Mod.Log.LogError((object)("The property " + array[2] + " on " + ((Component)renderer).gameObject.FullName() + " is not valid"));
						}
						else
						{
							if (!int.TryParse(array[3], out materialPropertyExport.fromID))
							{
								materialPropertyExport.fromName = array[3];
							}
							if (!int.TryParse(array[4], out materialPropertyExport.toID))
							{
								materialPropertyExport.toName = array[4];
							}
							materialProperties[result2].Add(materialPropertyExport);
						}
					}
				}
			}
		}

		private void CopyMaterialProperty(Material from, Material to, MaterialPropertyExport property)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			int num = property.fromID;
			if (num == -1)
			{
				num = Shader.PropertyToID(property.fromName);
			}
			int num2 = property.toID;
			if (num2 == -1)
			{
				num2 = Shader.PropertyToID(property.toName);
			}
			switch (property.type)
			{
			case PropertyType.Color:
				to.SetColor(num2, from.GetColor(num));
				break;
			case PropertyType.ColorArray:
				to.SetColorArray(num2, from.GetColorArray(num));
				break;
			case PropertyType.Float:
				to.SetFloat(num2, from.GetFloat(num));
				break;
			case PropertyType.FloatArray:
				to.SetFloatArray(num2, from.GetFloatArray(num));
				break;
			case PropertyType.Int:
				to.SetInt(num2, from.GetInt(num));
				break;
			case PropertyType.Matrix:
				to.SetMatrix(num2, from.GetMatrix(num));
				break;
			case PropertyType.MatrixArray:
				to.SetMatrixArray(num2, from.GetMatrixArray(num));
				break;
			case PropertyType.Texture:
				to.SetTexture(num2, from.GetTexture(num));
				break;
			case PropertyType.Vector:
				to.SetVector(num2, from.GetVector(num));
				break;
			case PropertyType.VectorArray:
				to.SetVectorArray(num2, from.GetVectorArray(num));
				break;
			}
		}

		private void AddMaterialColorChanger(ColorChanger colorChanger, Transform transform)
		{
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Expected O, but got Unknown
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			Renderer component = ((Component)transform).GetComponent<Renderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			List<UniformChanger> list = new List<UniformChanger>();
			for (int i = 0; i < transform.childCount; i++)
			{
				GameObject gameObject = ((Component)transform.GetChild(i)).gameObject;
				string text = ((Object)gameObject).name.ToLower();
				if (!text.StartsWith("#"))
				{
					continue;
				}
				text = text.Remove(0, 1);
				string[] array = text.Split(new char[1] { ';' });
				if (array.Length != 0 && array[0].Contains("color"))
				{
					if (array.Length != 6)
					{
						Mod.Instance.Errors.Add(array[0] + " property on " + ((Component)transform).gameObject.FullName() + " must have 5 arguments");
						Mod.Log.LogError((object)(array[0] + " property on " + ((Component)transform).gameObject.FullName() + " must have 5 arguments"));
						continue;
					}
					UniformChanger val = new UniformChanger();
					int.TryParse(array[1], out var result);
					val.materialIndex_ = result;
					val.colorType_ = ColorType(array[2]);
					val.name_ = UniformName(array[3]);
					float.TryParse(array[4], out var result2);
					val.mul_ = result2;
					val.alpha_ = string.Equals(array[5], "true", StringComparison.InvariantCultureIgnoreCase);
					list.Add(val);
				}
			}
			if (list.Count != 0)
			{
				RendererChanger item = new RendererChanger
				{
					renderer_ = component,
					uniformChangers_ = list.ToArray()
				};
				List<RendererChanger> list2 = colorChanger.rendererChangers_.ToList();
				list2.Add(item);
				colorChanger.rendererChangers_ = list2.ToArray();
			}
		}

		private ColorType ColorType(string name)
		{
			//IL_0044: 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_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			name = name.ToLower();
			return (ColorType)(name switch
			{
				"primary" => 0, 
				"secondary" => 1, 
				"glow" => 2, 
				"sparkle" => 3, 
				_ => 0, 
			});
		}

		private SupportedUniform UniformName(string name)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			name = name.ToLower();
			return (SupportedUniform)(name switch
			{
				"color" => 0, 
				"color2" => 1, 
				"emitcolor" => 2, 
				"reflectcolor" => 4, 
				"speccolor" => 5, 
				_ => 0, 
			});
		}

		private void SetCarVisuals(CarVisuals visuals, GameObject car)
		{
			if ((Object)(object)visuals == (Object)null)
			{
				Mod.Instance.Errors.Add("Can't find the CarVisuals component on the base car");
				Mod.Log.LogInfo((object)"Can't find the CarVisuals component on the base car");
				return;
			}
			SkinnedMeshRenderer componentInChildren = car.GetComponentInChildren<SkinnedMeshRenderer>();
			MakeMeshSkinned(componentInChildren);
			visuals.carBodyRenderer_ = componentInChildren;
			List<JetFlame> list = new List<JetFlame>();
			List<JetFlame> list2 = new List<JetFlame>();
			List<JetFlame> list3 = new List<JetFlame>();
			PlaceJets(car, list, list2, list3);
			visuals.boostJetFlames_ = list.ToArray();
			visuals.wingJetFlames_ = list2.ToArray();
			visuals.rotationJetFlames_ = list3.ToArray();
			visuals.driverPosition_ = FindCarDriver(car.transform);
			PlaceCarWheelsVisuals(visuals, car);
		}

		private void MakeMeshSkinned(SkinnedMeshRenderer renderer)
		{
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			Mesh sharedMesh = renderer.sharedMesh;
			if ((Object)(object)sharedMesh == (Object)null)
			{
				Mod.Instance.Errors.Add("The mesh on " + ((Component)renderer).gameObject.FullName() + " is null");
				Mod.Log.LogError((object)("The mesh on " + ((Component)renderer).gameObject.FullName() + " is null"));
			}
			else if (!sharedMesh.isReadable)
			{
				Mod.Instance.Errors.Add("Can't read the car mesh " + ((Object)sharedMesh).name + " on " + ((Component)renderer).gameObject.FullName() + "You must allow reading on it's unity inspector !");
				Mod.Log.LogError((object)("Can't read the car mesh " + ((Object)sharedMesh).name + " on " + ((Component)renderer).gameObject.FullName() + "You must allow reading on it's unity inspector !"));
			}
			else if (sharedMesh.vertices.Length != sharedMesh.boneWeights.Length)
			{
				BoneWeight[] array = (BoneWeight[])(object)new BoneWeight[sharedMesh.vertices.Length];
				for (int i = 0; i < array.Length; i++)
				{
					((BoneWeight)(ref array[i])).weight0 = 1f;
				}
				sharedMesh.boneWeights = array;
				Transform transform = ((Component)renderer).transform;
				sharedMesh.bindposes = (Matrix4x4[])(object)new Matrix4x4[1] { transform.worldToLocalMatrix * ((Component)renderer).transform.localToWorldMatrix };
				renderer.bones = (Transform[])(object)new Transform[1] { transform };
			}
		}

		private void PlaceJets(GameObject obj, List<JetFlame> boostJets, List<JetFlame> wingJets, List<JetFlame> rotationJets)
		{
			//IL_0075: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			int childCount = obj.transform.childCount;
			for (int i = 0; i < childCount; i++)
			{
				GameObject gameObject = GameObjectEx.GetChild(obj, i).gameObject;
				string text = ((Object)gameObject).name.ToLower();
				if ((Object)(object)infos_.boostJet != (Object)null && text.Contains("boostjet"))
				{
					GameObject val = Object.Instantiate<GameObject>(infos_.boostJet, gameObject.transform);
					val.transform.localPosition = Vector3.zero;
					val.transform.localRotation = Quaternion.identity;
					boostJets.Add(val.GetComponentInChildren<JetFlame>());
				}
				else if ((Object)(object)infos_.wingJet != (Object)null && text.Contains("wingjet"))
				{
					GameObject val2 = Object.Instantiate<GameObject>(infos_.wingJet, gameObject.transform);
					val2.transform.localPosition = Vector3.zero;
					val2.transform.localRotation = Quaternion.identity;
					wingJets.Add(val2.GetComponentInChildren<JetFlame>());
					ListEx.Last<JetFlame>(wingJets).rotationAxis_ = JetDirection(gameObject.transform);
				}
				else if ((Object)(object)infos_.rotationJet != (Object)null && text.Contains("rotationjet"))
				{
					GameObject val3 = Object.Instantiate<GameObject>(infos_.rotationJet, gameObject.transform);
					val3.transform.localPosition = Vector3.zero;
					val3.transform.localRotation = Quaternion.identity;
					rotationJets.Add(val3.GetComponentInChildren<JetFlame>());
					ListEx.Last<JetFlame>(rotationJets).rotationAxis_ = JetDirection(gameObject.transform);
				}
				else if ((Object)(object)infos_.wingTrail != (Object)null && text.Contains("wingtrail"))
				{
					GameObject val4 = Object.Instantiate<GameObject>(infos_.wingTrail, gameObject.transform);
					val4.transform.localPosition = Vector3.zero;
					val4.transform.localRotation = Quaternion.identity;
				}
				else
				{
					PlaceJets(gameObject, boostJets, wingJets, rotationJets);
				}
			}
		}

		private Vector3 JetDirection(Transform transform)
		{
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: 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_014b: 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_0182: 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)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			int childCount = transform.childCount;
			for (int i = 0; i < childCount; i++)
			{
				string text = ((Object)((Component)transform.GetChild(i)).gameObject).name.ToLower();
				if (!text.StartsWith("#"))
				{
					continue;
				}
				text = text.Remove(0, 1);
				string[] array = text.Split(new char[1] { ';' });
				if (array.Length != 0 && array[0].Contains("dir") && array.Length >= 2)
				{
					if (array[1] == "front")
					{
						return new Vector3(-1f, 0f, 0f);
					}
					if (array[1] == "back")
					{
						return new Vector3(1f, 0f, 0f);
					}
					if (array[1] == "left")
					{
						return new Vector3(0f, 1f, -1f);
					}
					if (array[1] == "right")
					{
						return new Vector3(0f, -1f, 1f);
					}
					if (array.Length == 4 && array[0].Contains("dir"))
					{
						Vector3 zero = Vector3.zero;
						float.TryParse(array[1], out zero.x);
						float.TryParse(array[2], out zero.y);
						float.TryParse(array[3], out zero.z);
						return zero;
					}
				}
			}
			return Vector3.zero;
		}

		private Transform FindCarDriver(Transform parent)
		{
			for (int i = 0; i < parent.childCount; i++)
			{
				Transform child = parent.GetChild(i);
				Transform val = ((((Object)((Component)child).gameObject).name.IndexOf("driverposition", StringComparison.InvariantCultureIgnoreCase) >= 0) ? child : FindCarDriver(child));
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return null;
		}

		private void PlaceCarWheelsVisuals(CarVisuals visual, GameObject car)
		{
			for (int i = 0; i < car.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)car.transform.GetChild(i)).gameObject;
				string text = ((Object)gameObject).name.ToLower();
				if (!text.Contains("wheel"))
				{
					continue;
				}
				CarWheelVisuals val = gameObject.AddComponent<CarWheelVisuals>();
				MeshRenderer[] componentsInChildren = gameObject.GetComponentsInChildren<MeshRenderer>();
				foreach (MeshRenderer val2 in componentsInChildren)
				{
					if (((Object)((Component)val2).gameObject).name.IndexOf("tire", StringComparison.InvariantCultureIgnoreCase) >= 0)
					{
						val.tire_ = val2;
						break;
					}
				}
				if (text.Contains("front"))
				{
					if (text.Contains("left"))
					{
						visual.wheelFL_ = val;
					}
					else if (text.Contains("right"))
					{
						visual.wheelFR_ = val;
					}
				}
				else if (text.Contains("back"))
				{
					if (text.Contains("left"))
					{
						visual.wheelBL_ = val;
					}
					else if (text.Contains("right"))
					{
						visual.wheelBR_ = val;
					}
				}
			}
		}

		private CarColors LoadDefaultColors(GameObject car)
		{
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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)
			CarColors val2 = default(CarColors);
			for (int i = 0; i < car.transform.childCount; i++)
			{
				GameObject gameObject = ((Component)car.transform.GetChild(i)).gameObject;
				string text = ((Object)gameObject).name.ToLower();
				if (!text.Contains("defaultcolor"))
				{
					continue;
				}
				for (int j = 0; j < gameObject.transform.childCount; j++)
				{
					GameObject gameObject2 = ((Component)gameObject.transform.GetChild(j)).gameObject;
					string text2 = ((Object)gameObject2).name.ToLower();
					if (!text2.StartsWith("#"))
					{
						continue;
					}
					text2 = text2.Remove(0, 1);
					string[] array = text2.Split(new char[1] { ';' });
					if (array.Length == 2)
					{
						Color val = ColorEx.HexToColor(array[1], byte.MaxValue);
						val.a = 1f;
						if (array[0] == "primary")
						{
							val2.primary_ = val;
						}
						else if (array[0] == "secondary")
						{
							val2.secondary_ = val;
						}
						else if (array[0] == "glow")
						{
							val2.glow_ = val;
						}
						else if (array[0] == "sparkle")
						{
							val2.sparkle_ = val;
						}
					}
				}
			}
			return infos_.defaultColors;
		}
	}
	public class CarInfos
	{
		public Dictionary<string, MaterialInfos> materials = new Dictionary<string, MaterialInfos>();

		public GameObject boostJet = null;

		public GameObject wingJet = null;

		public GameObject rotationJet = null;

		public GameObject wingTrail = null;

		public GameObject baseCar = null;

		public CarColors defaultColors;

		public void CollectInfos()
		{
			GetBaseCar();
			GetJetsAndTrail();
			GetMaterials();
		}

		private void GetBaseCar()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			GameObject carPrefab_ = G.Sys.ProfileManager_.carInfos_[0].prefabs_.carPrefab_;
			if ((Object)(object)carPrefab_ == (Object)null)
			{
				Mod.Instance.Errors.Add("Can't find the refractor base car prefab");
				return;
			}
			baseCar = carPrefab_;
			defaultColors = G.Sys.ProfileManager_.carInfos_[0].colors_;
		}

		private void GetJetsAndTrail()
		{
			if ((Object)(object)baseCar == (Object)null)
			{
				return;
			}
			JetFlame[] componentsInChildren = baseCar.GetComponentsInChildren<JetFlame>();
			foreach (JetFlame val in componentsInChildren)
			{
				switch (((Object)((Component)val).gameObject).name)
				{
				case "BoostJetFlameCenter":
					boostJet = ((Component)val).gameObject;
					break;
				case "JetFlameBackLeft":
					rotationJet = ((Component)val).gameObject;
					break;
				case "WingJetFlameLeft1":
					wingJet = ((Component)val).gameObject;
					break;
				}
			}
			wingTrail = ((Component)baseCar.GetComponentInChildren<WingTrail>()).gameObject;
			if ((Object)(object)boostJet == (Object)null)
			{
				Mod.Instance.Errors.Add("No valid BoostJet found on Refractor");
			}
			if ((Object)(object)rotationJet == (Object)null)
			{
				Mod.Instance.Errors.Add("No valid RotationJet found on Refractor");
			}
			if ((Object)(object)wingJet == (Object)null)
			{
				Mod.Instance.Errors.Add("No valid WingJet found on Refractor");
			}
			if ((Object)(object)wingTrail == (Object)null)
			{
				Mod.Instance.Errors.Add("No valid WingTrail found on Refractor");
			}
		}

		private void GetMaterials()
		{
			List<MaterialPropertyInfo> list = new List<MaterialPropertyInfo>
			{
				new MaterialPropertyInfo("Custom/LaserCut/CarPaint", "carpaint", 5, -1, -1),
				new MaterialPropertyInfo("Custom/LaserCut/CarWindow", "carwindow", -1, 218, 219),
				new MaterialPropertyInfo("Custom/Reflective/Bump Glow LaserCut", "wheel", 5, 218, 255),
				new MaterialPropertyInfo("Custom/LaserCut/CarPaintBump", "carpaintbump", 5, 218, -1),
				new MaterialPropertyInfo("Custom/Reflective/Bump Glow Interceptor Special", "interceptor", 5, 218, 255),
				new MaterialPropertyInfo("Custom/LaserCut/CarWindowTrans2Sided", "transparentglow", -1, 218, 219)
			};
			CarInfo[] carInfos_ = G.Sys.ProfileManager_.carInfos_;
			foreach (CarInfo val in carInfos_)
			{
				GameObject carPrefab_ = val.prefabs_.carPrefab_;
				Renderer[] componentsInChildren = carPrefab_.GetComponentsInChildren<Renderer>();
				foreach (Renderer val2 in componentsInChildren)
				{
					Material[] array = val2.materials;
					foreach (Material val3 in array)
					{
						foreach (MaterialPropertyInfo item in list)
						{
							if (!materials.ContainsKey(item.name) && ((Object)val3.shader).name == item.shaderName)
							{
								MaterialInfos value = new MaterialInfos
								{
									material = val3,
									diffuseIndex = item.diffuseIndex,
									normalIndex = item.normalIndex,
									emitIndex = item.emitIndex
								};
								materials.Add(item.name, value);
							}
						}
					}
				}
			}
			foreach (MaterialPropertyInfo item2 in list)
			{
				if (!materials.ContainsKey(item2.name))
				{
					Mod.Instance.Errors.Add("Can't find the material: " + item2.name + " - shader: " + item2.shaderName);
				}
			}
			materials.Add("donotreplace", new MaterialInfos());
		}
	}
	public class PrefabIndex
	{
		private static readonly string IndexPath;

		public Dictionary<string, PrefabIndexEntry> Files { get; set; } = new Dictionary<string, PrefabIndexEntry>();

		static PrefabIndex()
		{
			string directoryName = Path.GetDirectoryName(typeof(PrefabIndex).Assembly.Location);
			IndexPath = Path.Combine(directoryName, Path.Combine("Settings", "prefab_index.json"));
		}

		public string[] GetPrefabNames(string filePath)
		{
			if (Files.TryGetValue(filePath, out var value) && value.PrefabNames != null)
			{
				return value.PrefabNames;
			}
			return null;
		}

		public void SetPrefabNames(string filePath, string[] prefabNames)
		{
			Files[filePath] = new PrefabIndexEntry
			{
				LastWriteTime = GetLastWriteSafe(filePath),
				PrefabNames = (prefabNames ?? new string[0])
			};
		}

		public bool IsUpToDate(string filePath)
		{
			if (!Files.TryGetValue(filePath, out var value))
			{
				return false;
			}
			return value.LastWriteTime == GetLastWriteSafe(filePath);
		}

		public void RemoveStaleEntries(HashSet<string> validPaths)
		{
			List<string> list = new List<string>();
			foreach (string key in Files.Keys)
			{
				if (!validPaths.Contains(key))
				{
					list.Add(key);
				}
			}
			foreach (string item in list)
			{
				Files.Remove(item);
			}
		}

		private static long GetLastWriteSafe(string path)
		{
			try
			{
				return File.GetLastWriteTimeUtc(path).Ticks;
			}
			catch
			{
				return 0L;
			}
		}

		public void Load()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			try
			{
				if (!File.Exists(IndexPath))
				{
					return;
				}
				string text = File.ReadAllText(IndexPath);
				JsonReader val = new JsonReader();
				Dictionary<string, object> dictionary = ((DataReader<ModelTokenType>)(object)val).Read<Dictionary<string, object>>(text);
				if (dictionary == null)
				{
					return;
				}
				Files.Clear();
				foreach (KeyValuePair<string, object> item in dictionary)
				{
					if (!(item.Value is Dictionary<string, object> dictionary2))
					{
						continue;
					}
					PrefabIndexEntry prefabIndexEntry = new PrefabIndexEntry();
					if (dictionary2.TryGetValue("LastWriteTime", out var value))
					{
						prefabIndexEntry.LastWriteTime = Convert.ToInt64(value);
					}
					if (dictionary2.TryGetValue("PrefabNames", out var value2) && value2 is List<object> list)
					{
						prefabIndexEntry.PrefabNames = list.ConvertAll((object x) => x?.ToString() ?? string.Empty).ToArray();
					}
					Files[item.Key] = prefabIndexEntry;
				}
			}
			catch (Exception ex)
			{
				Mod.Log.LogWarning((object)("Failed to load prefab index: " + ex.Message));
				Files.Clear();
			}
		}

		public void Save()
		{
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			try
			{
				Dictionary<string, object> dictionary = new Dictionary<string, object>();
				foreach (KeyValuePair<string, PrefabIndexEntry> file in Files)
				{
					Dictionary<string, object> dictionary2 = new Dictionary<string, object>();
					dictionary2["LastWriteTime"] = file.Value.LastWriteTime;
					dictionary2["PrefabNames"] = new List<object>(file.Value.PrefabNames ?? new string[0]);
					Dictionary<string, object> value = dictionary2;
					dictionary[file.Key] = value;
				}
				string directoryName = Path.GetDirectoryName(IndexPath);
				if (!Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				JsonWriter val = new JsonWriter(new DataWriterSettings
				{
					PrettyPrint = true
				});
				File.WriteAllText(IndexPath, ((DataWriter<ModelTokenType>)(object)val).Write((object)dictionary));
			}
			catch (Exception ex)
			{
				Mod.Log.LogWarning((object)("Failed to save prefab index: " + ex.Message));
			}
		}
	}
	public class PrefabIndexEntry
	{
		public long LastWriteTime { get; set; }

		public string[] PrefabNames { get; set; } = new string[0];
	}
	public class CreateCarReturnInfos
	{
		public GameObject car;

		public CarColors colors;
	}
}