Decompiled source of ModelSwapLib v2.1.0

ModelSwapLib.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppLudiq;
using MelonLoader;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using ModelSwapLib;
using ModelSwapLib.Managers;
using ModelSwapLib.ObjectTracking;
using ModelSwapLib.Swapper;
using ModelSwapLib.Swapper.Modules;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "ModelSwapLib", "2.1.0", "CocoPopEater", null)]
[assembly: MelonGame("Keepsake Games", "Jump Space")]
[assembly: MelonColor(255, 0, 255, 0)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ModelSwapLib")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b61ef0eb25c6152fc962dc129c4d3eb812aa5bee")]
[assembly: AssemblyProduct("ModelSwapLib")]
[assembly: AssemblyTitle("ModelSwapLib")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 ModelSwapLib
{
	public class Core : MelonMod
	{
		public override void OnInitializeMelon()
		{
			BundleManager.GetInstance().InitializeBundles();
			TrackingManager.Initialize();
			ConsoleUtils.Msg("Initialized");
		}

		public override void OnDeinitializeMelon()
		{
			BundleManager.GetInstance().Shutdown();
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			TrackingManager.RebuildAllTrackingIds();
		}
	}
	internal static class ConsoleUtils
	{
		internal static void Msg(string message)
		{
			Melon<Core>.Logger.Msg(message);
		}

		internal static void Warning(string message)
		{
			Melon<Core>.Logger.Warning(message);
		}

		internal static void Error(string message)
		{
			Melon<Core>.Logger.Error(message);
		}

		internal static void BigError(string message)
		{
			Melon<Core>.Logger.BigError(message);
		}
	}
	public static class MeshUtils
	{
		public static Mesh MoveMesh(Mesh mesh, float x, float z, float y)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return MoveMesh(mesh, new Vector3(x, y, z));
		}

		public static Mesh MoveMesh(Mesh mesh, Vector3 pos)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			Vector3[] array = Il2CppArrayBase<Vector3>.op_Implicit((Il2CppArrayBase<Vector3>)(object)mesh.vertices);
			Vector3[] array2 = (Vector3[])(object)new Vector3[((Il2CppArrayBase<Vector3>)(object)mesh.vertices).Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = pos + array[i];
			}
			mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(array2);
			return mesh;
		}

		public static Mesh RotateMesh(Mesh mesh, float x, float y, float z)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			Quaternion qAngle = Quaternion.Euler(x, y, z);
			return RotateMesh(mesh, qAngle);
		}

		public static Mesh RotateMesh(Mesh mesh, Quaternion qAngle)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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)
			Vector3[] array = Il2CppArrayBase<Vector3>.op_Implicit((Il2CppArrayBase<Vector3>)(object)mesh.vertices);
			Vector3[] array2 = (Vector3[])(object)new Vector3[((Il2CppArrayBase<Vector3>)(object)mesh.vertices).Length];
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = qAngle * array[i];
			}
			mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(array2);
			return mesh;
		}

		public static Mesh ScaleMesh(Mesh mesh, float x, float y, float z)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			return ScaleMesh(mesh, new Vector3(x, y, z));
		}

		public static Mesh ScaleMesh(Mesh mesh, Vector3 scale)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0052: 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)
			Vector3[] array = Il2CppArrayBase<Vector3>.op_Implicit((Il2CppArrayBase<Vector3>)(object)mesh.vertices);
			Vector3[] array2 = (Vector3[])(object)new Vector3[((Il2CppArrayBase<Vector3>)(object)mesh.vertices).Length];
			for (int i = 0; i < array.Length; i++)
			{
				Vector3 val = array[i];
				array2[i] = new Vector3(val.x * scale.x, val.y * scale.y, val.z * scale.z);
			}
			mesh.vertices = Il2CppStructArray<Vector3>.op_Implicit(array2);
			return mesh;
		}
	}
}
namespace ModelSwapLib.ObjectTracking
{
	internal static class TrackingManager
	{
		private static bool Initialized;

		private static HashSet<int> _trackedIds;

		private static Dictionary<string, HashSet<int>> _nameMap;

		internal static IEnumerable<int> TrackedIds => _trackedIds;

		internal static Dictionary<string, HashSet<int>> NameMap => _nameMap;

		internal static void Initialize()
		{
			if (!Initialized)
			{
				ConsoleUtils.Msg("Initializing tracking manager...");
				_trackedIds = new HashSet<int>();
				_nameMap = new Dictionary<string, HashSet<int>>();
				Initialized = true;
			}
		}

		internal static IEnumerable<GameObject> GetObjectsFromNames(IEnumerable<string> names)
		{
			List<GameObject> list = new List<GameObject>();
			foreach (string name in names)
			{
				list.AddRange(GetObjectsFromName(name));
			}
			return list;
		}

		internal static IEnumerable<GameObject> GetObjectsFromName(string name)
		{
			List<GameObject> list = new List<GameObject>();
			try
			{
				_nameMap.TryGetValue(name, out var value);
				foreach (int item in value)
				{
					Object obj = Object.FindObjectFromInstanceID(item);
					GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
					if (!Object.op_Implicit((Object)(object)val))
					{
						ForceObjectReprocess(name, item);
					}
					else if (((Object)val).name != name)
					{
						ForceObjectReprocess(name, item);
					}
					else
					{
						list.Add(val);
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		private static void ForceObjectReprocess(string apparentName, int objectId)
		{
			RemoveTrackingDetails(apparentName, objectId);
			Object val = Object.FindObjectFromInstanceID(objectId);
			if (Object.op_Implicit(val))
			{
				GameObject val2 = (GameObject)(object)((val is GameObject) ? val : null);
				if (val2 != null)
				{
					AddTrackingDetails(val2);
				}
			}
		}

		internal static IEnumerable<int> GetObjectIdsByName(string name)
		{
			try
			{
				_nameMap.TryGetValue(name, out var value);
				return value;
			}
			catch (Exception)
			{
				return Enumerable.Empty<int>();
			}
		}

		internal static IEnumerable<int> GetAllObjectsFromNames(IEnumerable<string> names)
		{
			List<int> list = new List<int>();
			foreach (string name in names)
			{
				try
				{
					list.AddRange(GetObjectIdsByName(name));
				}
				catch (Exception)
				{
				}
			}
			return list;
		}

		internal static void RebuildAllTrackingIds()
		{
			_trackedIds.Clear();
			_nameMap.Clear();
			foreach (GameObject item in ((IEnumerable<GameObject>)Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0)).ToList())
			{
				AddTrackingDetails(item);
			}
		}

		internal static void AddTrackingDetails(GameObject gameObject)
		{
			AddTrackingDetails(((Object)gameObject).name, ((Object)gameObject).GetInstanceID());
			MelonCoroutines.Start(ObjectActionManager.GetInstance().HandleObject(gameObject));
		}

		private static void AddTrackingDetails(string name, int trackingId)
		{
			if (!_trackedIds.Contains(trackingId))
			{
				_trackedIds.Add(trackingId);
				if (!_nameMap.TryGetValue(name, out var value))
				{
					_nameMap.Add(name, new HashSet<int>(new <>z__ReadOnlySingleElementList<int>(trackingId)));
					return;
				}
				value.Add(trackingId);
				_nameMap[name] = value;
			}
		}

		internal static void RemoveTrackingDetails(GameObject gameObject)
		{
			RemoveTrackingDetails(((Object)gameObject).name, ((Object)gameObject).GetInstanceID());
		}

		private static void RemoveTrackingDetails(string name, int trackingId)
		{
			if (_nameMap.TryGetValue(name, out var value))
			{
				value.Remove(trackingId);
				_trackedIds.Remove(trackingId);
			}
		}
	}
}
namespace ModelSwapLib.Swapper
{
	public class ObjectActionManager
	{
		private static ObjectActionManager instance;

		private Dictionary<string, List<Swapper>> ObjectActions = new Dictionary<string, List<Swapper>>();

		private Dictionary<Guid, Swapper> SwapperCache = new Dictionary<Guid, Swapper>();

		private HashSet<string> SkipCache = new HashSet<string>();

		private ObjectActionManager()
		{
			instance = this;
		}

		public static ObjectActionManager GetInstance()
		{
			if (instance == null)
			{
				instance = new ObjectActionManager();
			}
			return instance;
		}

		internal IEnumerator HandleObject(GameObject obj)
		{
			if (!Object.op_Implicit((Object)(object)obj) || SkipCache.Contains(((Object)obj).name))
			{
				yield break;
			}
			if (!ObjectActions.TryGetValue(((Object)obj).name, out var actions))
			{
				SkipCache.Add(((Object)obj).name);
				yield break;
			}
			if (actions == null || actions.Count == 0)
			{
				SkipCache.Add(((Object)obj).name);
				yield break;
			}
			yield return (object)new WaitForEndOfFrame();
			if (!Object.op_Implicit((Object)(object)obj))
			{
				yield break;
			}
			foreach (Swapper item in actions)
			{
				item.RunAllModules(obj);
				item.DeactivateObjects();
			}
		}

		public Guid RegisterSwapper(Swapper swapper)
		{
			if (!swapper.Validate())
			{
				return Guid.Empty;
			}
			foreach (string objectName in swapper.ObjectNames)
			{
				ObjectActions.TryGetValue(objectName, out var value);
				if (value == null)
				{
					value = new List<Swapper>();
					value.Add(swapper);
					ObjectActions[objectName] = value;
				}
				else if (!value.Contains(swapper))
				{
					value.Add(swapper);
				}
			}
			SwapperCache.Add(swapper.SwapperGuid, swapper);
			foreach (GameObject objectsFromName in TrackingManager.GetObjectsFromNames(swapper.ObjectNames))
			{
				swapper.RunAllModules(objectsFromName);
			}
			swapper.DeactivateObjects();
			foreach (string objectName2 in swapper.ObjectNames)
			{
				if (SkipCache.Contains(objectName2))
				{
					SkipCache.Remove(objectName2);
				}
			}
			return swapper.SwapperGuid;
		}

		public void ClearSkipCache()
		{
			SkipCache.Clear();
			TrackingManager.RebuildAllTrackingIds();
		}

		public Swapper GetSwapper(Guid swapperGuid)
		{
			return SwapperCache.GetValueOrDefault(swapperGuid, null);
		}

		public void UnregisterSwapper(Guid swapperGuid)
		{
			if (!(swapperGuid == Guid.Empty))
			{
				UnregisterSwapper(SwapperCache.GetValueOrDefault(swapperGuid, null));
			}
		}

		public void UnregisterSwapper(Swapper swapper)
		{
			if (swapper == null || !swapper.Validate())
			{
				return;
			}
			foreach (KeyValuePair<string, List<Swapper>> objectAction in ObjectActions)
			{
				List<Swapper> value = objectAction.Value;
				if (value.Contains(swapper))
				{
					value.Remove(swapper);
				}
			}
			SwapperCache.Remove(swapper.SwapperGuid);
		}
	}
	public class Swapper
	{
		public string ModName { get; set; }

		public string SwapperName { get; set; } = "Default Name";


		public List<string> ObjectNames { get; set; }

		public string BundleName { get; set; }

		public List<IAssetModule> AssetModules { get; set; }

		public List<ITransformModule> TransformModules { get; set; }

		public List<string> Deactivations { get; set; }

		public Guid SwapperGuid { get; internal set; }

		public Swapper(string modName, string swapperName, List<string> objectNames, string bundleName, List<IAssetModule> assetModules, List<ITransformModule> transformModules, List<string> deactivations)
		{
			ModName = modName;
			SwapperName = swapperName;
			ObjectNames = objectNames;
			BundleName = bundleName;
			AssetModules = assetModules;
			TransformModules = transformModules;
			Deactivations = deactivations;
		}

		public Swapper()
		{
		}

		internal void RunAllModules(GameObject target)
		{
			if (!Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			if (AssetModules != null)
			{
				AssetBundle bundle = BundleManager.GetInstance().GetBundle(this);
				if ((Object)(object)bundle == (Object)null)
				{
					ConsoleUtils.Error("Failed to load AssetBundle from Mod:Swapper : " + ModName + ":" + SwapperName);
				}
				else
				{
					foreach (IAssetModule assetModule in AssetModules)
					{
						assetModule.Apply(target, bundle);
					}
				}
			}
			if (TransformModules == null)
			{
				return;
			}
			foreach (ITransformModule transformModule in TransformModules)
			{
				transformModule.Apply(target);
			}
		}

		internal void DeactivateObjects()
		{
			if (Deactivations == null || Deactivations.Count == 0)
			{
				return;
			}
			foreach (GameObject objectsFromName in TrackingManager.GetObjectsFromNames(Deactivations))
			{
				objectsFromName.SetActive(false);
			}
		}

		internal Guid GenerateSwapperGuid()
		{
			if (SwapperGuid == Guid.Empty)
			{
				SwapperGuid = Guid.NewGuid();
			}
			return SwapperGuid;
		}

		public bool Validate()
		{
			if (string.IsNullOrEmpty(ModName))
			{
				return false;
			}
			if (ObjectNames == null || ObjectNames.Count == 0)
			{
				return false;
			}
			if (AssetModules != null && AssetModules.Count > 0)
			{
				if (BundleName == null)
				{
					return false;
				}
				if (!BundleName.EndsWith(".bundle"))
				{
					BundleName += ".bundle";
				}
			}
			else
			{
				if (TransformModules == null || TransformModules.Count == 0)
				{
					return false;
				}
				if (Deactivations == null || Deactivations.Count == 0)
				{
					return false;
				}
			}
			GenerateSwapperGuid();
			return true;
		}
	}
	public class SwapperBuilder
	{
		private string ModName;

		private string SwapperName;

		private List<string> ObjectNames = new List<string>();

		private string BundleName;

		private List<IAssetModule> AssetModules;

		private List<ITransformModule> TransformModules;

		private List<string> Deactivations;

		public SwapperBuilder(string ModName)
		{
			this.ModName = ModName;
		}

		public SwapperBuilder()
		{
		}

		public SwapperBuilder SetModName(string ModName)
		{
			this.ModName = ModName;
			return this;
		}

		public SwapperBuilder SetSwapperName(string SwapperName)
		{
			this.SwapperName = SwapperName;
			return this;
		}

		public SwapperBuilder AddObjectName(string ObjectName)
		{
			ObjectNames.Add(ObjectName);
			return this;
		}

		public SwapperBuilder AddObjectNames(List<string> BundleNames)
		{
			ObjectNames.AddRange(BundleNames);
			return this;
		}

		public SwapperBuilder SetBundleName(string BundleName)
		{
			this.BundleName = BundleName;
			return this;
		}

		public SwapperBuilder AddAssetModule(IAssetModule assetModule)
		{
			if (AssetModules == null)
			{
				AssetModules = new List<IAssetModule>();
			}
			AssetModules.Add(assetModule);
			return this;
		}

		public SwapperBuilder AddAssetModules(List<IAssetModule> assetModules)
		{
			if (AssetModules == null)
			{
				AssetModules = new List<IAssetModule>();
			}
			AssetModules.AddRange(assetModules);
			return this;
		}

		public SwapperBuilder AddTransformModule(ITransformModule transformModule)
		{
			if (TransformModules == null)
			{
				TransformModules = new List<ITransformModule>();
			}
			TransformModules.Add(transformModule);
			return this;
		}

		public SwapperBuilder AddTransformModules(List<ITransformModule> transformModules)
		{
			if (TransformModules == null)
			{
				TransformModules = new List<ITransformModule>();
			}
			TransformModules.AddRange(transformModules);
			return this;
		}

		public SwapperBuilder AddDeactivation(string deactivation)
		{
			if (Deactivations == null)
			{
				Deactivations = new List<string>();
			}
			Deactivations.Add(deactivation);
			return this;
		}

		public SwapperBuilder AddDeactivations(List<string> deactivations)
		{
			if (Deactivations == null)
			{
				Deactivations = new List<string>();
			}
			Deactivations.AddRange(deactivations);
			return this;
		}

		public Swapper Build()
		{
			if (ModName == null)
			{
				return null;
			}
			if (ObjectNames == null || ObjectNames.Count == 0)
			{
				return null;
			}
			if (BundleName == null && AssetModules != null && AssetModules.Count > 0)
			{
				return null;
			}
			if ((AssetModules == null || AssetModules.Count == 0) && (TransformModules == null || TransformModules.Count == 0) && (Deactivations == null || Deactivations.Count == 0))
			{
				return null;
			}
			return new Swapper(ModName, SwapperName, ObjectNames, BundleName, AssetModules, TransformModules, Deactivations);
		}
	}
}
namespace ModelSwapLib.Swapper.Modules
{
	public class ColorDetailModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public ColorDetailModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public ColorDetailModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Color Detail Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_ColorDetailLookup"))
				{
					item.SetTexture("_ColorDetailLookup", (Texture)(object)val);
				}
			}
		}
	}
	public class ColorMainModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public ColorMainModule(string assetPath)
		{
		}

		public ColorMainModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Color Main Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_ColorMainLookup"))
				{
					item.SetTexture("_ColorMainLookup", (Texture)(object)val);
				}
			}
		}
	}
	public class ColorSecondaryModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public ColorSecondaryModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public ColorSecondaryModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Color Secondary Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_ColorSecondaryLookup"))
				{
					item.SetTexture("_ColorSecondaryLookup", (Texture)(object)val);
				}
			}
		}
	}
	public class EmmisionsModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public EmmisionsModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public EmmisionsModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Emissions Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_T3"))
				{
					item.SetTexture("_T3", (Texture)(object)val);
				}
			}
		}
	}
	public class MeshFilterModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public MeshFilterModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Mesh val = bundle.LoadAsset<Mesh>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Mesh: " + AssetPath);
				return;
			}
			MeshFilter component = obj.GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null))
			{
				component.mesh = val;
			}
		}
	}
	[Obsolete("This class is deprecated. Use SkinnedMeshModule instead")]
	public class MeshModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public MeshModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Mesh val = bundle.LoadAsset<Mesh>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Mesh: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				component.sharedMesh = val;
			}
		}
	}
	public class MetallicModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public MetallicModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public MetallicModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Metallic Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_M"))
				{
					item.SetTexture("_M", (Texture)(object)val);
				}
			}
		}
	}
	public class NormalsModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public NormalsModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public NormalsModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Normals Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
			if (materials == null || ((Il2CppArrayBase<Material>)(object)materials).Length == 0)
			{
				return;
			}
			foreach (Material item in (Il2CppArrayBase<Material>)(object)materials)
			{
				if (item.HasProperty("_T2"))
				{
					item.SetTexture("_T2", (Texture)(object)val);
				}
			}
		}
	}
	public class SkinnedMeshModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public SkinnedMeshModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Mesh val = bundle.LoadAsset<Mesh>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Mesh: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				component.sharedMesh = val;
			}
		}
	}
	public class Texture2DModule : IAssetModule, IModule
	{
		public string AssetPath { get; set; }

		public Texture2DModule(string assetPath)
		{
			AssetPath = assetPath;
		}

		public Texture2DModule()
		{
		}

		public void Apply(GameObject obj, AssetBundle bundle)
		{
			Texture2D val = bundle.LoadAsset<Texture2D>(AssetPath);
			if ((Object)(object)val == (Object)null)
			{
				ConsoleUtils.Error("Failed to load Main Texture2D: " + AssetPath);
				return;
			}
			SkinnedMeshRenderer component = obj.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				Il2CppReferenceArray<Material> materials = ((Renderer)component).materials;
				if (((Il2CppArrayBase<Material>)(object)materials)[0].HasProperty("_T1"))
				{
					((Il2CppArrayBase<Material>)(object)materials)[0].SetTexture("_T1", (Texture)(object)val);
				}
			}
		}
	}
	public interface IAssetModule : IModule
	{
		string AssetPath { get; set; }

		void Apply(GameObject obj, AssetBundle bundle);

		void ApplyAll(IEnumerable<GameObject> objects, AssetBundle assetBundle)
		{
			foreach (GameObject @object in objects)
			{
				Apply(@object, assetBundle);
			}
		}
	}
	public interface IModule
	{
	}
	public interface ITransformModule : IModule
	{
		void Apply(GameObject obj);

		void ApplyAll(IEnumerable<GameObject> objects)
		{
			foreach (GameObject @object in objects)
			{
				Apply(@object);
			}
		}
	}
}
namespace ModelSwapLib.Swapper.Modules.ITransformModules
{
	public class MoveMeshModule : ITransformModule, IModule
	{
		private Vector3 vector;

		public MoveMeshModule(float xDist, float yDist, float zDist)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			vector = new Vector3(xDist, yDist, zDist);
		}

		public MoveMeshModule(Vector3 vector)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			this.vector = vector;
		}

		public void Apply(GameObject gameObject)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			SkinnedMeshRenderer component = gameObject.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				Mesh val = new Mesh();
				component.BakeMesh(val);
				if (!((Object)(object)val == (Object)null))
				{
					val = MeshUtils.MoveMesh(val, vector);
					component.sharedMesh = val;
				}
			}
		}
	}
	public class RotateMeshModule : ITransformModule, IModule
	{
		private Vector3 vector;

		public RotateMeshModule(float xRot, float yRot, float zRot)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			vector = new Vector3(xRot, yRot, zRot);
		}

		public RotateMeshModule(Vector3 vector)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			this.vector = vector;
		}

		public void Apply(GameObject gameObject)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			SkinnedMeshRenderer component = gameObject.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				Mesh val = new Mesh();
				component.BakeMesh(val);
				if (!((Object)(object)val == (Object)null))
				{
					val = MeshUtils.RotateMesh(val, vector.x, vector.y, vector.z);
					component.sharedMesh = val;
				}
			}
		}
	}
	public class ScaleMeshModule : ITransformModule, IModule
	{
		private Vector3 vector;

		public ScaleMeshModule(float xScale, float yScale, float zScale)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			vector = new Vector3(xScale, yScale, zScale);
		}

		public ScaleMeshModule(Vector3 vector)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			this.vector = vector;
		}

		public void Apply(GameObject gameObject)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			SkinnedMeshRenderer component = gameObject.GetComponent<SkinnedMeshRenderer>();
			if (!((Object)(object)component == (Object)null))
			{
				Mesh val = new Mesh();
				component.BakeMesh(val);
				if (!((Object)(object)val == (Object)null))
				{
					val = MeshUtils.ScaleMesh(val, vector);
					component.sharedMesh = val;
				}
			}
		}
	}
}
namespace ModelSwapLib.Managers
{
	public class BundleManager
	{
		private static BundleManager _instance;

		private readonly Dictionary<string, AssetBundle> _bundles = new Dictionary<string, AssetBundle>();

		private BundleManager()
		{
			_instance = this;
		}

		public static BundleManager GetInstance()
		{
			if (_instance == null)
			{
				_instance = new BundleManager();
			}
			return _instance;
		}

		internal void InitializeBundles()
		{
			_bundles.Clear();
			string modsDirectory = MelonEnvironment.ModsDirectory;
			FindBundlesRecursive(modsDirectory);
		}

		private void FindBundlesRecursive(string rootDir)
		{
			string[] files = Directory.GetFiles(rootDir);
			foreach (string text in files)
			{
				if (text.EndsWith(".bundle"))
				{
					string fileName = Path.GetFileName(text);
					ConsoleUtils.Msg("Found Bundle: " + fileName);
					_bundles.Add(fileName, AssetBundle.LoadFromFile(text));
				}
			}
			files = Directory.GetDirectories(rootDir);
			foreach (string text2 in files)
			{
				if (new DirectoryInfo(text2).LinkTarget == null)
				{
					FindBundlesRecursive(text2);
				}
			}
		}

		internal AssetBundle GetBundle(ModelSwapLib.Swapper.Swapper swapper)
		{
			string key = ((!swapper.BundleName.EndsWith(".bundle")) ? (swapper.BundleName + ".bundle") : swapper.BundleName);
			_bundles.TryGetValue(key, out var value);
			if ((Object)(object)value != (Object)null)
			{
				return value;
			}
			return null;
		}

		internal void Shutdown()
		{
			foreach (AssetBundle value in _bundles.Values)
			{
				try
				{
					if (value != null)
					{
						value.Unload(true);
					}
				}
				catch (Exception)
				{
				}
			}
			_bundles.Clear();
		}
	}
}
namespace ModelSwapLib.Harmony
{
	[HarmonyPatch]
	public class HarmonyPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Object), "Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Transform),
			typeof(bool)
		})]
		[HarmonyPatch(typeof(Object), "Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion)
		})]
		[HarmonyPatch(typeof(Object), "Instantiate", new Type[]
		{
			typeof(Object),
			typeof(Vector3),
			typeof(Quaternion),
			typeof(Transform)
		})]
		private static void InstantiatePostfix(ref Object __result)
		{
			if (__result == (Object)null)
			{
				return;
			}
			GameObject val = ComponentHolderProtocol.GameObject(__result);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			TrackingManager.AddTrackingDetails(val);
			Transform[] array = Il2CppArrayBase<Transform>.op_Implicit(val.GetComponentsInChildren<Transform>());
			foreach (Transform val2 in array)
			{
				if (!((Object)(object)((Component)val2).gameObject == __result))
				{
					TrackingManager.AddTrackingDetails(((Component)val2).gameObject);
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Object), "Destroy", new Type[] { typeof(Object) })]
		private static void Prefix_Object(Object obj)
		{
			if (Object.op_Implicit(obj))
			{
				GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null);
				if (val != null)
				{
					TrackingManager.RemoveTrackingDetails(val);
				}
			}
		}
	}
}
internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T>
{
	private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T>
	{
		object IEnumerator.Current => _item;

		T IEnumerator<T>.Current => _item;

		public Enumerator(T item)
		{
			_item = item;
		}

		bool IEnumerator.MoveNext()
		{
			if (!_moveNextCalled)
			{
				return _moveNextCalled = true;
			}
			return false;
		}

		void IEnumerator.Reset()
		{
			_moveNextCalled = false;
		}

		void IDisposable.Dispose()
		{
		}
	}

	int ICollection.Count => 1;

	bool ICollection.IsSynchronized => false;

	object ICollection.SyncRoot => this;

	object IList.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	bool IList.IsFixedSize => true;

	bool IList.IsReadOnly => true;

	int IReadOnlyCollection<T>.Count => 1;

	T IReadOnlyList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
	}

	int ICollection<T>.Count => 1;

	bool ICollection<T>.IsReadOnly => true;

	T IList<T>.this[int index]
	{
		get
		{
			if (index != 0)
			{
				throw new IndexOutOfRangeException();
			}
			return _item;
		}
		set
		{
			throw new NotSupportedException();
		}
	}

	public <>z__ReadOnlySingleElementList(T item)
	{
		_item = item;
	}

	IEnumerator IEnumerable.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection.CopyTo(Array array, int index)
	{
		array.SetValue(_item, index);
	}

	int IList.Add(object value)
	{
		throw new NotSupportedException();
	}

	void IList.Clear()
	{
		throw new NotSupportedException();
	}

	bool IList.Contains(object value)
	{
		return EqualityComparer<T>.Default.Equals(_item, (T)value);
	}

	int IList.IndexOf(object value)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, (T)value))
		{
			return -1;
		}
		return 0;
	}

	void IList.Insert(int index, object value)
	{
		throw new NotSupportedException();
	}

	void IList.Remove(object value)
	{
		throw new NotSupportedException();
	}

	void IList.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}

	IEnumerator<T> IEnumerable<T>.GetEnumerator()
	{
		return new Enumerator(_item);
	}

	void ICollection<T>.Add(T item)
	{
		throw new NotSupportedException();
	}

	void ICollection<T>.Clear()
	{
		throw new NotSupportedException();
	}

	bool ICollection<T>.Contains(T item)
	{
		return EqualityComparer<T>.Default.Equals(_item, item);
	}

	void ICollection<T>.CopyTo(T[] array, int arrayIndex)
	{
		array[arrayIndex] = _item;
	}

	bool ICollection<T>.Remove(T item)
	{
		throw new NotSupportedException();
	}

	int IList<T>.IndexOf(T item)
	{
		if (!EqualityComparer<T>.Default.Equals(_item, item))
		{
			return -1;
		}
		return 0;
	}

	void IList<T>.Insert(int index, T item)
	{
		throw new NotSupportedException();
	}

	void IList<T>.RemoveAt(int index)
	{
		throw new NotSupportedException();
	}
}