Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LegacyEnemySkinsBridge v1.1.2
LegacyEnemySkinsBridge.dll
Decompiled 5 hours agousing 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; } } }