Decompiled source of LegacyEnemySkinsBridge v1.1.2

LegacyEnemySkinsBridge.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.RegularExpressions;
using AntlerShed.SkinRegistry;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("LegacyEnemySkinsBridge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("LegacyEnemySkinsBridge")]
[assembly: AssemblyTitle("LegacyEnemySkinsBridge")]
[assembly: AssemblyVersion("1.1.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 LegacyEnemySkinsBridge
{
	[BepInPlugin("legacyskinsbridge.plugin", "Legacy Enemy Skins Bridge", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "legacyskinsbridge.plugin";

		public const string PluginName = "Legacy Enemy Skins Bridge";

		public const string PluginVersion = "1.1.1";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private ConfigEntry<bool> _enabled;

		private ConfigEntry<bool> _automaticDiscovery;

		private ConfigEntry<float> _defaultFrequency;

		private static readonly LegacySkinDefinition[] Definitions = new LegacySkinDefinition[18]
		{
			new LegacySkinDefinition("Better Ghost (Cheems)", "LegacyBridge.Ghost.Cheems", "LethalCompany.GhostGirl", "BetterGhost", "BetterGhost.Patches.DressGirlAIPatch", "StartPatch", "Cheemful-BetterGhost"),
			new LegacySkinDefinition("Flandre Ghost Girl", "LegacyBridge.Ghost.Flandre", "LethalCompany.GhostGirl", "FlandreGhostGirl", "FlandreGhost.Patches.DressGirlAIPatch", "StartPatch", "Catalyss-FlandreGhostGirl"),
			new LegacySkinDefinition("FNaF Endoskeleton", "LegacyBridge.Coil.Endo", "LethalCompany.Coilhead", "FNaFEndoCoilhead", "FNaFEndoCoilhead.Patches.SpringManPatch", "Postfix", "OrtonLongGaming-FNaFEndoCoilhead"),
			new LegacySkinDefinition("SCP-173", "LegacyBridge.Coil.SCP173", "LethalCompany.Coilhead", "SCP_173", "SCP_173.Patches.CoilheadPatch", "Summon173", "raydenoir-SCP173CoilheadSFX"),
			new LegacySkinDefinition("Weeping Angel", "LegacyBridge.Coil.WeepingAngel", "LethalCompany.Coilhead", "WeepingAngel", "WeepingAngel.Patches.CoilheadPatch", "Summon173", "raydenoir-WeepingAngels"),
			new LegacySkinDefinition("Better Coilhead", "LegacyBridge.Coil.Better", "LethalCompany.Coilhead", "NewCoil", "NewCoil.Patches.NewCoilPatch", "CoilPreLoadPatch", "lethal_coder-BetterCoilheadModel"),
			new LegacySkinDefinition("Freddy Bracken", "LegacyBridge.Bracken.Freddy", "LethalCompany.Bracken", "FreddyBracken", "FreddyBracken.Patches.FlowermanPatch", "Postfix", "OrtonLongGaming-FreddyBracken"),
			new LegacySkinDefinition("Better Bracken", "LegacyBridge.Bracken.Better", "LethalCompany.Bracken", "ModelRequestA", "ModelRequestA.Patches.BrackenPatch", "DioPreLoadPatch", "lethal_coder-BetterBrackenModel"),
			new LegacySkinDefinition("Freminet Butler", "LegacyBridge.Butler.Freminet", "LethalCompany.Butler", "FreminetButler", "FreminetButler.FremModBase", "PluginDetectButler", "GoblinKingShmee-FreminetButlerMod"),
			new LegacySkinDefinition("Minecraft Spider", "LegacyBridge.Spider.Minecraft", "LethalCompany.BunkerSpider", "MinecraftSpiderMod", "MinecraftSpiderMod.Patches.SandSpiderAIPatch", "Start", "Legoking236-MinecraftSpiderMod"),
			new LegacySkinDefinition("FNaF Puppet Jester", "LegacyBridge.Jester.Puppet", "LethalCompany.Jester", "PuppetJester", "PuppetJester.Patches.JesterPatch", "Postfix", "OrtonLongGaming-PuppetJester"),
			new LegacySkinDefinition("TBH Creature", "LegacyBridge.HoarderBug.TBH", "LethalCompany.HoarderBug", "snrk.tbhCreature", "YippeeBugMod.YippeeBug.Patches.HoarderBugPatch", "Postfix", "snrk-tbhCreatureReplacementMod"),
			new LegacySkinDefinition("Touhou Sekibanki", "LegacyBridge.Touhou.Sekibanki", "LethalCompany.Coilhead", "TouhouEnemyModels", "TouhouEnemyModels.Patches", "ReplaceEnemyModels", "BeanCan-TouhouEnemyModels"),
			new LegacySkinDefinition("Touhou Satori", "LegacyBridge.Touhou.Satori", "LethalCompany.Nutcracker", "TouhouEnemyModels", "TouhouEnemyModels.Patches", "ReplaceEnemyModels", "BeanCan-TouhouEnemyModels"),
			new LegacySkinDefinition("Touhou Suika", "LegacyBridge.Touhou.Suika", "LethalCompany.ForestKeeper", "TouhouEnemyModels", "TouhouEnemyModels.Patches", "ReplaceEnemyModels", "BeanCan-TouhouEnemyModels"),
			new LegacySkinDefinition("Touhou Marisa", "LegacyBridge.Touhou.Marisa", "LethalCompany.HoarderBug", "TouhouEnemyModels", "TouhouEnemyModels.Patches", "ReplaceEnemyModels", "BeanCan-TouhouEnemyModels"),
			new LegacySkinDefinition("Touhou Utsuho", "LegacyBridge.Touhou.Utsuho", "LethalCompany.OldBird", "TouhouEnemyModels", "TouhouEnemyModels.V50Patches", "ReplaceUtsuhoTheme", "BeanCan-TouhouEnemyModels"),
			new LegacySkinDefinition("Touhou Yuyuko", "LegacyBridge.Touhou.Yuyuko", "LethalCompany.EarthLeviathan", "TouhouEnemyModels", "TouhouEnemyModels.Patches", "ReplaceEnemyModels", "BeanCan-TouhouEnemyModels")
		};

		private void Awake()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Convert supported legacy enemy model replacers into Enemy Skin Registry variants. Restart required after changing this option.");
			_automaticDiscovery = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Automatic discovery", true, "Also detect simple enemy model replacers that are not in the built-in compatibility catalog. Restart required.");
			_defaultFrequency = ((BaseUnityPlugin)this).Config.Bind<float>("General", "New skin default frequency", 0.25f, new ConfigDescription("Initial Enemy Skin Registry frequency assigned to newly discovered skins.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			_enabled.SettingChanged += delegate
			{
				Log.LogWarning((object)"Enabled changed. Restart the game to safely apply the new bridge state.");
			};
			_automaticDiscovery.SettingChanged += delegate
			{
				Log.LogWarning((object)"Automatic discovery changed. Restart the game to safely apply the new bridge state.");
			};
			if (!_enabled.Value)
			{
				Log.LogInfo((object)"Legacy model conversion is disabled in config. Original replacers will run normally.");
				return;
			}
			_harmony = new Harmony("legacyskinsbridge.plugin");
			((MonoBehaviour)this).StartCoroutine(InitializeAfterPlugins());
		}

		private IEnumerator InitializeAfterPlugins()
		{
			yield return null;
			List<LegacySkinDefinition> list = Definitions.ToList();
			if (_automaticDiscovery.Value)
			{
				list.AddRange(DiscoverSimpleReplacers(list));
			}
			int num = 0;
			foreach (LegacySkinDefinition item in list)
			{
				if (!item.Resolve())
				{
					Log.LogWarning((object)("Skipping " + item.Label + ": source assembly or patch method was not found."));
					continue;
				}
				int num2 = UnpatchAutomaticReplacement(item.PatchMethod);
				if (num2 == 0)
				{
					Log.LogWarning((object)(item.Label + ": the automatic replacement patch was not found; duplicate models may still occur."));
				}
				else
				{
					Log.LogInfo((object)$"Disabled {num2} automatic patch(es) for {item.Label}.");
				}
				try
				{
					EnemySkinRegistry.RegisterSkin((Skin)(object)new LegacySkin(item), (DefaultSkinConfigData?)new DefaultSkinConfigData(Array.Empty<DefaultSkinConfigEntry>(), Mathf.Clamp01(_defaultFrequency.Value), 0.25f));
					num++;
				}
				catch (Exception arg)
				{
					Log.LogError((object)$"Could not register {item.Label}: {arg}");
				}
			}
			Log.LogInfo((object)$"Registered {num} legacy model replacements as mutually exclusive Enemy Skin Registry skins.");
		}

		private IEnumerable<LegacySkinDefinition> DiscoverSimpleReplacers(IEnumerable<LegacySkinDefinition> catalog)
		{
			List<LegacySkinDefinition> list = new List<LegacySkinDefinition>();
			HashSet<MethodInfo> hashSet = new HashSet<MethodInfo>(from definition in catalog
				where definition.Resolve()
				select definition.PatchMethod);
			MethodBase[] array = Harmony.GetAllPatchedMethods().ToArray();
			foreach (MethodBase methodBase in array)
			{
				if (!IsEnemyInitializationMethod(methodBase, out var enemyId, out var label))
				{
					continue;
				}
				Patches patchInfo = Harmony.GetPatchInfo(methodBase);
				if (patchInfo == null)
				{
					continue;
				}
				foreach (Patch item in patchInfo.Prefixes.Concat(patchInfo.Postfixes))
				{
					MethodInfo patchMethod = item.PatchMethod;
					if (patchMethod == null || hashSet.Contains(patchMethod))
					{
						continue;
					}
					Assembly assembly = patchMethod.DeclaringType?.Assembly;
					if (!(assembly == null) && !(assembly == typeof(Plugin).Assembly) && !(assembly == typeof(EnemySkinRegistry).Assembly))
					{
						string text = FindPackageRoot(assembly.Location);
						if (TryReadLegacyModelPackage(text, out var packageName))
						{
							string id = $"AutoBridge.{SanitizeId(assembly.GetName().Name)}.{SanitizeId(label)}.{patchMethod.MetadataToken}";
							LegacySkinDefinition legacySkinDefinition = new LegacySkinDefinition(packageName + " (" + label + ")", id, enemyId, patchMethod, Path.Combine(text, "icon.png"));
							hashSet.Add(patchMethod);
							list.Add(legacySkinDefinition);
							Log.LogInfo((object)("Automatically discovered enemy model replacer: " + legacySkinDefinition.Label + "."));
						}
					}
				}
			}
			return list;
		}

		private static bool IsEnemyInitializationMethod(MethodBase method, out string enemyId, out string label)
		{
			enemyId = null;
			label = null;
			Type declaringType = method.DeclaringType;
			if (declaringType == null || !typeof(EnemyAI).IsAssignableFrom(declaringType) || (method.Name != "Start" && method.Name != "Awake" && method.Name != "OnEnable"))
			{
				return false;
			}
			(enemyId, label) = declaringType.Name switch
			{
				"BaboonBirdAI" => ("LethalCompany.BaboonHawk", "Baboon Hawk"), 
				"ClaySurgeonAI" => ("LethalCompany.Barber", "Barber"), 
				"FlowermanAI" => ("LethalCompany.Bracken", "Bracken"), 
				"SandSpiderAI" => ("LethalCompany.BunkerSpider", "Bunker Spider"), 
				"ButlerEnemyAI" => ("LethalCompany.Butler", "Butler"), 
				"SpringManAI" => ("LethalCompany.Coilhead", "Coilhead"), 
				"SandWormAI" => ("LethalCompany.EarthLeviathan", "Earth Leviathan"), 
				"MouthDogAI" => ("LethalCompany.EyelessDog", "Eyeless Dog"), 
				"ForestGiantAI" => ("LethalCompany.ForestKeeper", "Forest Keeper"), 
				"DressGirlAI" => ("LethalCompany.GhostGirl", "Ghost Girl"), 
				"HoarderBugAI" => ("LethalCompany.HoarderBug", "Hoarding Bug"), 
				"BlobAI" => ("LethalCompany.Hygrodere", "Hygrodere"), 
				"JesterAI" => ("LethalCompany.Jester", "Jester"), 
				"NutcrackerEnemyAI" => ("LethalCompany.Nutcracker", "Nutcracker"), 
				"RadMechAI" => ("LethalCompany.OldBird", "Old Bird"), 
				"CentipedeAI" => ("LethalCompany.SnareFlea", "Snare Flea"), 
				"PufferAI" => ("LethalCompany.SporeLizard", "Spore Lizard"), 
				"CrawlerAI" => ("LethalCompany.Thumper", "Thumper"), 
				_ => (null, null), 
			};
			return enemyId != null;
		}

		private static string FindPackageRoot(string assemblyPath)
		{
			if (string.IsNullOrWhiteSpace(assemblyPath))
			{
				return string.Empty;
			}
			DirectoryInfo directoryInfo = new FileInfo(assemblyPath).Directory;
			string value = Path.GetFullPath(Paths.PluginPath).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
			int num = 0;
			while (directoryInfo != null && num < 5 && directoryInfo.FullName.StartsWith(value, StringComparison.OrdinalIgnoreCase))
			{
				if (File.Exists(Path.Combine(directoryInfo.FullName, "manifest.json")))
				{
					return directoryInfo.FullName;
				}
				num++;
				directoryInfo = directoryInfo.Parent;
			}
			return string.Empty;
		}

		private static bool TryReadLegacyModelPackage(string packageRoot, out string packageName)
		{
			packageName = null;
			if (string.IsNullOrWhiteSpace(packageRoot))
			{
				return false;
			}
			try
			{
				string text = File.ReadAllText(Path.Combine(packageRoot, "manifest.json"));
				if (text.IndexOf("EnemySkinRegistry", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("EnemySkinKit", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return false;
				}
				Match match = Regex.Match(text, "\\\"description\\\"\\s*:\\s*\\\"(?<value>(?:\\\\.|[^\\\"])*)\\\"", RegexOptions.IgnoreCase);
				if (!Regex.IsMatch(match.Success ? match.Groups["value"].Value : string.Empty, "replac|reskin|enemy model|creature model", RegexOptions.IgnoreCase))
				{
					return false;
				}
				Match match2 = Regex.Match(text, "\\\"name\\\"\\s*:\\s*\\\"(?<value>(?:\\\\.|[^\\\"])*)\\\"", RegexOptions.IgnoreCase);
				packageName = (match2.Success ? match2.Groups["value"].Value : new DirectoryInfo(packageRoot).Name);
				return true;
			}
			catch (Exception ex)
			{
				Log.LogDebug((object)("Could not inspect package manifest at " + packageRoot + ": " + ex.Message));
				return false;
			}
		}

		private static string SanitizeId(string value)
		{
			return Regex.Replace(value ?? "Unknown", "[^A-Za-z0-9_.-]", string.Empty);
		}

		private int UnpatchAutomaticReplacement(MethodInfo patchMethod)
		{
			int num = 0;
			MethodBase[] array = Harmony.GetAllPatchedMethods().ToArray();
			foreach (MethodBase methodBase in array)
			{
				Patches patchInfo = Harmony.GetPatchInfo(methodBase);
				if (patchInfo != null)
				{
					Patch[] array2 = (from p in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers)
						where p.PatchMethod == patchMethod
						select p).ToArray();
					for (int num2 = 0; num2 < array2.Length; num2++)
					{
						_ = array2[num2];
						_harmony.Unpatch(methodBase, patchMethod);
						num++;
					}
				}
			}
			return num;
		}
	}
	internal sealed class LegacySkinDefinition
	{
		private Texture2D _icon;

		private readonly string _iconPath;

		public string Label { get; }

		public string Id { get; }

		public string EnemyId { get; }

		public string AssemblyName { get; }

		public string PatchTypeName { get; }

		public string PatchMethodName { get; }

		public string PackageFolder { get; }

		public MethodInfo PatchMethod { get; private set; }

		public LegacySkinDefinition(string label, string id, string enemyId, string assemblyName, string patchTypeName, string patchMethodName, string packageFolder)
		{
			Label = label;
			Id = id;
			EnemyId = enemyId;
			AssemblyName = assemblyName;
			PatchTypeName = patchTypeName;
			PatchMethodName = patchMethodName;
			PackageFolder = packageFolder;
		}

		public LegacySkinDefinition(string label, string id, string enemyId, MethodInfo patchMethod, string iconPath)
		{
			Label = label;
			Id = id;
			EnemyId = enemyId;
			AssemblyName = patchMethod.DeclaringType?.Assembly.GetName().Name ?? string.Empty;
			PatchTypeName = patchMethod.DeclaringType?.FullName ?? string.Empty;
			PatchMethodName = patchMethod.Name;
			PackageFolder = string.Empty;
			PatchMethod = patchMethod;
			_iconPath = iconPath;
		}

		public bool Resolve()
		{
			if (PatchMethod != null)
			{
				return true;
			}
			PatchMethod = (AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => string.Equals(a.GetName().Name, AssemblyName, StringComparison.OrdinalIgnoreCase))?.GetType(PatchTypeName, throwOnError: false))?.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == PatchMethodName && m.GetParameters().Any((ParameterInfo p) => typeof(EnemyAI).IsAssignableFrom(UnwrapByRef(p.ParameterType))));
			return PatchMethod != null;
		}

		public Texture2D GetIcon()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			if ((Object)(object)_icon != (Object)null)
			{
				return _icon;
			}
			_icon = new Texture2D(2, 2, (TextureFormat)4, false)
			{
				name = Id + ".Icon"
			};
			try
			{
				string path = (string.IsNullOrWhiteSpace(_iconPath) ? Path.Combine(Paths.PluginPath, PackageFolder, "icon.png") : _iconPath);
				if (File.Exists(path))
				{
					ImageConversion.LoadImage(_icon, File.ReadAllBytes(path));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not load icon for " + Label + ": " + ex.Message));
			}
			return _icon;
		}

		private static Type UnwrapByRef(Type type)
		{
			if (!type.IsByRef)
			{
				return type;
			}
			return type.GetElementType();
		}
	}
	internal sealed class LegacySkin : Skin
	{
		private readonly LegacySkinDefinition _definition;

		public string Label => _definition.Label;

		public string Id => _definition.Id;

		public string EnemyId => _definition.EnemyId;

		public Texture2D Icon => _definition.GetIcon();

		public LegacySkin(LegacySkinDefinition definition)
		{
			_definition = definition;
		}

		public Skinner CreateSkinner()
		{
			return (Skinner)(object)new LegacySkinner(_definition);
		}
	}
	internal sealed class LegacySkinner : Skinner
	{
		private readonly LegacySkinDefinition _definition;

		private LegacySnapshot _snapshot;

		public LegacySkinner(LegacySkinDefinition definition)
		{
			_definition = definition;
		}

		public void Apply(GameObject enemy)
		{
			if ((Object)(object)enemy == (Object)null)
			{
				return;
			}
			try
			{
				_snapshot = new LegacySnapshot(enemy);
				object[] parameters = BuildArguments(_definition.PatchMethod, enemy);
				object obj = (_definition.PatchMethod.IsStatic ? null : FindPluginInstance(_definition.PatchMethod.DeclaringType));
				_definition.PatchMethod.Invoke(obj, parameters);
				Plugin.Log.LogDebug((object)("Applied " + _definition.Label + " to " + ((Object)enemy).name + "."));
			}
			catch (TargetInvocationException ex)
			{
				Plugin.Log.LogError((object)$"{_definition.Label} failed while applying: {ex.InnerException ?? ex}");
				_snapshot?.Restore(enemy);
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"{_definition.Label} failed while applying: {arg}");
				_snapshot?.Restore(enemy);
			}
		}

		public void Remove(GameObject enemy)
		{
			try
			{
				_snapshot?.Restore(enemy);
				_snapshot = null;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"{_definition.Label} failed while restoring the original model: {arg}");
			}
		}

		private static object[] BuildArguments(MethodInfo method, GameObject enemy)
		{
			EnemyAI val = enemy.GetComponent<EnemyAI>() ?? enemy.GetComponentInParent<EnemyAI>();
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				Type type = (parameterType.IsByRef ? parameterType.GetElementType() : parameterType);
				if (type.IsInstanceOfType(val))
				{
					array[i] = val;
				}
				else if (type == typeof(GameObject))
				{
					array[i] = enemy;
				}
				else if (typeof(Component).IsAssignableFrom(type))
				{
					array[i] = enemy.GetComponent(type) ?? enemy.GetComponentInChildren(type, true);
				}
				else
				{
					array[i] = (type.IsValueType ? Activator.CreateInstance(type) : null);
				}
			}
			return array;
		}

		private static object FindPluginInstance(Type type)
		{
			return Object.FindObjectsOfType(type).FirstOrDefault();
		}
	}
	internal sealed class LegacySnapshot
	{
		private sealed class GameObjectState
		{
			private readonly Transform _transform;

			private readonly Transform _parent;

			private readonly string _name;

			private readonly bool _active;

			private readonly int _layer;

			private readonly Vector3 _position;

			private readonly Quaternion _rotation;

			private readonly Vector3 _scale;

			public GameObjectState(Transform transform)
			{
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				_transform = transform;
				_parent = transform.parent;
				_name = ((Object)((Component)transform).gameObject).name;
				_active = ((Component)transform).gameObject.activeSelf;
				_layer = ((Component)transform).gameObject.layer;
				_position = transform.localPosition;
				_rotation = transform.localRotation;
				_scale = transform.localScale;
			}

			public void Restore()
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_transform == (Object)null))
				{
					_transform.SetParent(_parent, false);
					_transform.localPosition = _position;
					_transform.localRotation = _rotation;
					_transform.localScale = _scale;
					((Object)((Component)_transform).gameObject).name = _name;
					((Component)_transform).gameObject.layer = _layer;
					((Component)_transform).gameObject.SetActive(_active);
				}
			}
		}

		private sealed class RendererState
		{
			private readonly Renderer _renderer;

			private readonly bool _enabled;

			private readonly Material[] _materials;

			public RendererState(Renderer renderer)
			{
				_renderer = renderer;
				_enabled = renderer.enabled;
				_materials = renderer.sharedMaterials;
			}

			public void Restore()
			{
				if (!((Object)(object)_renderer == (Object)null))
				{
					_renderer.enabled = _enabled;
					_renderer.sharedMaterials = _materials;
				}
			}
		}

		private sealed class MeshFilterState
		{
			private readonly MeshFilter _filter;

			private readonly Mesh _mesh;

			public MeshFilterState(MeshFilter filter)
			{
				_filter = filter;
				_mesh = filter.sharedMesh;
			}

			public void Restore()
			{
				if ((Object)(object)_filter != (Object)null)
				{
					_filter.sharedMesh = _mesh;
				}
			}
		}

		private sealed class SkinnedMeshState
		{
			private readonly SkinnedMeshRenderer _renderer;

			private readonly Mesh _mesh;

			private readonly Transform _rootBone;

			private readonly Transform[] _bones;

			public SkinnedMeshState(SkinnedMeshRenderer renderer)
			{
				_renderer = renderer;
				_mesh = renderer.sharedMesh;
				_rootBone = renderer.rootBone;
				_bones = renderer.bones;
			}

			public void Restore()
			{
				if (!((Object)(object)_renderer == (Object)null))
				{
					_renderer.sharedMesh = _mesh;
					_renderer.rootBone = _rootBone;
					_renderer.bones = _bones;
				}
			}
		}

		private sealed class AnimatorState
		{
			private readonly Animator _animator;

			private readonly RuntimeAnimatorController _controller;

			private readonly Avatar _avatar;

			private readonly bool _enabled;

			private readonly bool _rootMotion;

			private readonly AnimatorCullingMode _culling;

			private readonly AnimatorUpdateMode _updateMode;

			public AnimatorState(Animator animator)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_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)
				_animator = animator;
				_controller = animator.runtimeAnimatorController;
				_avatar = animator.avatar;
				_enabled = ((Behaviour)animator).enabled;
				_rootMotion = animator.applyRootMotion;
				_culling = animator.cullingMode;
				_updateMode = animator.updateMode;
			}

			public void Restore()
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_animator == (Object)null))
				{
					_animator.runtimeAnimatorController = _controller;
					_animator.avatar = _avatar;
					((Behaviour)_animator).enabled = _enabled;
					_animator.applyRootMotion = _rootMotion;
					_animator.cullingMode = _culling;
					_animator.updateMode = _updateMode;
				}
			}
		}

		private readonly HashSet<int> _existingObjects;

		private readonly List<GameObjectState> _gameObjects;

		private readonly List<RendererState> _renderers;

		private readonly List<MeshFilterState> _meshFilters;

		private readonly List<SkinnedMeshState> _skinnedMeshes;

		private readonly List<AnimatorState> _animators;

		public LegacySnapshot(GameObject root)
		{
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			_existingObjects = new HashSet<int>(componentsInChildren.Select((Transform t) => ((Object)((Component)t).gameObject).GetInstanceID()));
			_gameObjects = componentsInChildren.Select((Transform t) => new GameObjectState(t)).ToList();
			_renderers = (from r in root.GetComponentsInChildren<Renderer>(true)
				select new RendererState(r)).ToList();
			_meshFilters = (from m in root.GetComponentsInChildren<MeshFilter>(true)
				select new MeshFilterState(m)).ToList();
			_skinnedMeshes = (from m in root.GetComponentsInChildren<SkinnedMeshRenderer>(true)
				select new SkinnedMeshState(m)).ToList();
			_animators = (from a in root.GetComponentsInChildren<Animator>(true)
				select new AnimatorState(a)).ToList();
		}

		public void Restore(GameObject root)
		{
			if ((Object)(object)root == (Object)null)
			{
				return;
			}
			foreach (Transform item in root.GetComponentsInChildren<Transform>(true).OrderByDescending(GetDepth))
			{
				if ((Object)(object)item != (Object)(object)root.transform && !_existingObjects.Contains(((Object)((Component)item).gameObject).GetInstanceID()))
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
			}
			foreach (GameObjectState gameObject in _gameObjects)
			{
				gameObject.Restore();
			}
			foreach (RendererState renderer in _renderers)
			{
				renderer.Restore();
			}
			foreach (MeshFilterState meshFilter in _meshFilters)
			{
				meshFilter.Restore();
			}
			foreach (SkinnedMeshState skinnedMesh in _skinnedMeshes)
			{
				skinnedMesh.Restore();
			}
			foreach (AnimatorState animator in _animators)
			{
				animator.Restore();
			}
		}

		private static int GetDepth(Transform transform)
		{
			int num = 0;
			while ((Object)(object)transform.parent != (Object)null)
			{
				num++;
				transform = transform.parent;
			}
			return num;
		}
	}
}