Decompiled source of Ending Keepsakes v1.0.0

BepInEx/plugins/EndingKeepsakes/EndingKeepsakes.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[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("EndingKeepsakes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EndingKeepsakes")]
[assembly: AssemblyTitle("EndingKeepsakes")]
[assembly: AssemblyVersion("1.0.0.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 EndingKeepsakes
{
	internal sealed class AppearanceSnapshot : IDisposable
	{
		internal sealed class Piece
		{
			internal string Bone;

			internal string Name;

			internal Vector3 Position;

			internal Vector3 Scale;

			internal Quaternion Rotation;

			internal Mesh Mesh;

			internal Material[] Materials;

			internal MaterialPropertyBlock Properties;
		}

		internal sealed class AttachResult
		{
			internal readonly List<GameObject> Roots = new List<GameObject>();

			internal int Meshes;

			internal int MissingBones;
		}

		private readonly List<Piece> pieces = new List<Piece>();

		private readonly List<Object> owned = new List<Object>();

		private int arrows;

		private int thorns;

		private int items;

		private int backpacks;

		private int ticks;

		private int stickyItems;

		internal string Summary => $"arrows={arrows}, thorns={thorns}, heldItems={items}, backpacks={backpacks}, ticks={ticks}, stickyItems={stickyItems}, meshes={pieces.Count}";

		internal static AppearanceSnapshot Capture(Character character)
		{
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			AppearanceSnapshot appearanceSnapshot = new AppearanceSnapshot();
			try
			{
				HashSet<Transform> bones = new HashSet<Transform>(character.refs.mainRenderer.bones.Where((Transform b) => Object.op_Implicit((Object)(object)b)).ToArray());
				Bodypart[] componentsInChildren = ((Component)character).GetComponentsInChildren<Bodypart>(true);
				ThornOnMe[] componentsInChildren2 = ((Component)character).GetComponentsInChildren<ThornOnMe>(true);
				if (Plugin.Instance.KeepThorns.Value)
				{
					foreach (ThornOnMe item in componentsInChildren2.Where((ThornOnMe t) => t.stuckIn))
					{
						Transform node = ((Component)item).transform;
						Matrix4x4 world = ((Component)item).transform.localToWorldMatrix;
						if (Plugin.Instance.thornOrigins.TryGetValue(item, out var value) && Object.op_Implicit((Object)(object)value.Parent))
						{
							node = value.Parent;
							world = value.Parent.localToWorldMatrix * value.Local;
						}
						Transform val = FindAnchor(node, bones);
						if (!Object.op_Implicit((Object)(object)val))
						{
							Plugin.Warn("No source bone for " + ((Object)item).name);
							continue;
						}
						appearanceSnapshot.AddVisual(((Component)item).transform, val, world, forceRoot: true);
						if (item.isArrow)
						{
							appearanceSnapshot.arrows++;
						}
						else
						{
							appearanceSnapshot.thorns++;
						}
					}
				}
				Bodypart val2 = ((IEnumerable<Bodypart>)componentsInChildren).FirstOrDefault((Func<Bodypart, bool>)((Bodypart p) => (int)p.partType == 10));
				Item currentItem = character.data.currentItem;
				if (Plugin.Instance.KeepHeldItem.Value && Object.op_Implicit((Object)(object)currentItem) && Object.op_Implicit((Object)(object)val2))
				{
					Transform val3 = FindAnchor(val2.transform, bones);
					if (Object.op_Implicit((Object)(object)val3))
					{
						Matrix4x4 localToWorldMatrix = currentItem.transform.localToWorldMatrix;
						appearanceSnapshot.AddVisual(currentItem.transform, val3, localToWorldMatrix, forceRoot: true);
						appearanceSnapshot.items++;
					}
				}
				if (Plugin.Instance.KeepBackpack.Value && (Object)(object)character.player != (Object)null && (int)character.player.backpackSlot.backpackType != 0 && (!character.refs.items.currentSelectedSlot.IsSome || character.refs.items.currentSelectedSlot.Value != 3))
				{
					BackpackOnBackVisuals activeBackpackVisuals = character.refs.backpackHandler.activeBackpackVisuals;
					if (Object.op_Implicit((Object)(object)activeBackpackVisuals) && Object.op_Implicit((Object)(object)activeBackpackVisuals.view))
					{
						Transform val4 = FindAnchor(((Component)activeBackpackVisuals).transform, bones) ?? FindAnchor(character.refs.backpackTransform, bones);
						if (Object.op_Implicit((Object)(object)val4))
						{
							appearanceSnapshot.AddVisual(((Component)activeBackpackVisuals).transform, val4, ((Component)activeBackpackVisuals).transform.localToWorldMatrix, forceRoot: true, activeBackpackVisuals.view.transform);
							appearanceSnapshot.backpacks++;
						}
					}
				}
				appearanceSnapshot.CaptureAttachedObjects(character, componentsInChildren, bones);
				return appearanceSnapshot;
			}
			catch
			{
				appearanceSnapshot.Dispose();
				throw;
			}
		}

		private void CaptureAttachedObjects(Character character, Bodypart[] bodyparts, HashSet<Transform> bones)
		{
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0275: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Instance.KeepTicks.Value)
			{
				Bodypart val = ((IEnumerable<Bodypart>)bodyparts).FirstOrDefault((Func<Bodypart, bool>)((Bodypart p) => (int)p.partType == 15));
				KeyValuePair<Bugfix, Character>[] array = Bugfix.AllAttachedBugs.ToArray();
				for (int num = 0; num < array.Length; num++)
				{
					KeyValuePair<Bugfix, Character> keyValuePair = array[num];
					Bugfix key = keyValuePair.Key;
					if (!Object.op_Implicit((Object)(object)key) || (Object)(object)keyValuePair.Value != (Object)(object)character || !((Component)key).gameObject.activeInHierarchy)
					{
						continue;
					}
					Transform val2 = (Object.op_Implicit((Object)(object)val) ? FindAnchor(val.transform, bones) : null);
					if (!Object.op_Implicit((Object)(object)val2))
					{
						Plugin.Warn("No source leg bone for attached tick.");
						continue;
					}
					try
					{
						int count = pieces.Count;
						AddVisual(((Component)key).transform, val2, ((Component)key).transform.localToWorldMatrix, forceRoot: false);
						if (pieces.Count > count)
						{
							ticks++;
						}
					}
					catch (Exception ex)
					{
						Plugin.Warn("Could not capture one attached tick: " + ex);
					}
				}
			}
			if (!Plugin.Instance.KeepStickyItems.Value)
			{
				return;
			}
			HashSet<StickyItemComponent> hashSet = new HashSet<StickyItemComponent>();
			StickyItemComponent[] array2 = StickyItemComponent.ALL_STUCK_ITEMS.ToArray();
			foreach (StickyItemComponent sticky in array2)
			{
				if (!Object.op_Implicit((Object)(object)sticky) || !hashSet.Add(sticky) || (Object)(object)sticky.stuckToCharacter != (Object)(object)character || !((Component)sticky).gameObject.activeInHierarchy)
				{
					continue;
				}
				Item item = ((ItemComponent)sticky).item;
				if (!Object.op_Implicit((Object)(object)item) || (int)item.itemState != 0 || (Object)(object)item == (Object)(object)character.data.currentItem)
				{
					continue;
				}
				Bodypart val3 = ((IEnumerable<Bodypart>)bodyparts).FirstOrDefault((Func<Bodypart, bool>)((Bodypart p) => p.partType == sticky.stuckToBodypart));
				Transform val4 = (Object.op_Implicit((Object)(object)val3) ? FindAnchor(val3.transform, bones) : null);
				if (!Object.op_Implicit((Object)(object)val4))
				{
					Plugin.Warn("No source bone for stuck item " + ((Object)sticky).name);
					continue;
				}
				try
				{
					int count2 = pieces.Count;
					AddVisual(item.transform, val4, item.transform.localToWorldMatrix, forceRoot: false);
					if (pieces.Count > count2)
					{
						stickyItems++;
					}
				}
				catch (Exception ex2)
				{
					Plugin.Warn("Could not capture one stuck item: " + ex2);
				}
			}
		}

		private static Transform FindAnchor(Transform node, HashSet<Transform> bones)
		{
			while (Object.op_Implicit((Object)(object)node))
			{
				if (bones.Contains(node))
				{
					return node;
				}
				node = node.parent;
			}
			return null;
		}

		private void AddVisual(Transform root, Transform anchor, Matrix4x4 world, bool forceRoot, Transform forceExtra = null)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Invalid comparison between Unknown and I4
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!val.enabled || (int)val.shadowCastingMode == 3 || !VisibleUnder(((Component)val).transform, root, forceRoot, forceExtra))
				{
					continue;
				}
				Mesh val2;
				if (val is MeshRenderer)
				{
					MeshFilter component = ((Component)val).GetComponent<MeshFilter>();
					if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh))
					{
						continue;
					}
					val2 = component.sharedMesh;
				}
				else
				{
					SkinnedMeshRenderer val3 = (SkinnedMeshRenderer)(object)((val is SkinnedMeshRenderer) ? val : null);
					if (val3 == null || !Object.op_Implicit((Object)(object)val3.sharedMesh))
					{
						continue;
					}
					val2 = new Mesh
					{
						name = "KeepsakeBakedMesh"
					};
					owned.Add((Object)(object)val2);
					val3.BakeMesh(val2);
				}
				Matrix4x4 val4 = Matrix4x4.identity;
				Transform val5 = ((Component)val).transform;
				while ((Object)(object)val5 != (Object)(object)root)
				{
					val4 = Matrix4x4.TRS(val5.localPosition, val5.localRotation, val5.localScale) * val4;
					val5 = val5.parent;
				}
				Matrix4x4 val6 = anchor.worldToLocalMatrix * world * val4;
				Material[] materials = CopyMaterials(val.sharedMaterials, owned);
				MaterialPropertyBlock val7 = new MaterialPropertyBlock();
				val.GetPropertyBlock(val7);
				val7.SetFloat("_Interactable", 0f);
				val7.SetFloat("_VertexGhost", 0f);
				pieces.Add(new Piece
				{
					Name = ((Object)val).name,
					Bone = ((Object)anchor).name,
					Position = Vector4.op_Implicit(((Matrix4x4)(ref val6)).GetColumn(3)),
					Rotation = ((Matrix4x4)(ref val6)).rotation,
					Scale = ((Matrix4x4)(ref val6)).lossyScale,
					Mesh = val2,
					Materials = materials,
					Properties = val7
				});
			}
		}

		private static Material[] CopyMaterials(Material[] source, List<Object> owned)
		{
			return ((IEnumerable<Material>)source).Select((Func<Material, Material>)delegate(Material material)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Expected O, but got Unknown
				if (!Object.op_Implicit((Object)(object)material))
				{
					return (Material)null;
				}
				Material val = new Material(material);
				if (val.HasProperty("_Interactable"))
				{
					val.SetFloat("_Interactable", 0f);
				}
				if (val.HasProperty("_VertexGhost"))
				{
					val.SetFloat("_VertexGhost", 0f);
				}
				owned.Add((Object)(object)val);
				return val;
			}).ToArray();
		}

		private static bool VisibleUnder(Transform node, Transform root, bool forceRoot, Transform forceExtra = null)
		{
			while (Object.op_Implicit((Object)(object)node))
			{
				if (!((Component)node).gameObject.activeSelf && !((Object)(object)node == (Object)(object)root && forceRoot) && (Object)(object)node != (Object)(object)forceExtra)
				{
					return false;
				}
				if ((Object)(object)node == (Object)(object)root)
				{
					return true;
				}
				node = node.parent;
			}
			return false;
		}

		internal AttachResult Attach(Transform target, int layer)
		{
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			AttachResult attachResult = new AttachResult();
			Dictionary<string, Transform> dictionary = (from t in ((Component)target).GetComponentsInChildren<Transform>(true)
				group t by ((Object)t).name into g
				where g.Count() == 1
				select g).ToDictionary((IGrouping<string, Transform> g) => g.Key, (IGrouping<string, Transform> g) => g.First());
			foreach (Piece piece in pieces)
			{
				if (!dictionary.TryGetValue(piece.Bone, out var value))
				{
					attachResult.MissingBones++;
					Plugin.Warn("Missing/ambiguous ending bone: " + piece.Bone + " for " + piece.Name);
					continue;
				}
				GameObject val = new GameObject("Keepsake_" + piece.Name)
				{
					layer = layer
				};
				val.transform.SetParent(value, false);
				val.transform.localPosition = piece.Position;
				val.transform.localRotation = piece.Rotation;
				val.transform.localScale = piece.Scale;
				val.AddComponent<KeepsakeMarker>();
				val.AddComponent<MeshFilter>().sharedMesh = piece.Mesh;
				MeshRenderer obj = val.AddComponent<MeshRenderer>();
				((Renderer)obj).sharedMaterials = piece.Materials;
				((Renderer)obj).SetPropertyBlock(piece.Properties);
				attachResult.Roots.Add(val);
				attachResult.Meshes++;
			}
			return attachResult;
		}

		public void Dispose()
		{
			foreach (Object item in owned)
			{
				if (Object.op_Implicit(item))
				{
					Object.Destroy(item);
				}
			}
			owned.Clear();
			pieces.Clear();
		}
	}
	[BepInPlugin("ritsukage.peak.endingkeepsakes", "Ending Keepsakes", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(PeakHandler), "PrepareEndCutscene")]
		private static class CapturePatch
		{
			[HarmonyPrefix]
			[HarmonyPriority(800)]
			private static void Prefix()
			{
				try
				{
					Instance.CaptureAll();
				}
				catch (Exception ex)
				{
					Warn("Ending capture failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(PeakHandler), "SetCosmetic")]
		private static class ApplyPatch
		{
			[HarmonyPostfix]
			private static void Postfix(Character character, CustomizationRefs customizationRef)
			{
				try
				{
					Instance.Apply(character, customizationRef);
				}
				catch (Exception ex)
				{
					Warn("Ending attachment failed: " + ex);
				}
			}
		}

		[HarmonyPatch(typeof(CharacterAfflictions), "InitThorns")]
		private static class ThornOriginPatch
		{
			[HarmonyPrefix]
			private static void Prefix(CharacterAfflictions __instance)
			{
				try
				{
					ThornOnMe[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<ThornOnMe>(true);
					foreach (ThornOnMe val in componentsInChildren)
					{
						if (!Instance.thornOrigins.ContainsKey(val))
						{
							Instance.thornOrigins.Add(val, new ThornOrigin(((Component)val).transform));
						}
					}
				}
				catch (Exception ex)
				{
					Warn("Could not record original thorn anchors: " + ex);
				}
			}
		}

		public const string Id = "ritsukage.peak.endingkeepsakes";

		internal static Plugin Instance;

		internal ConfigEntry<bool> KeepThorns;

		internal ConfigEntry<bool> KeepHeldItem;

		internal ConfigEntry<bool> KeepBackpack;

		internal ConfigEntry<bool> KeepTicks;

		internal ConfigEntry<bool> KeepStickyItems;

		private ConfigEntry<bool> enabledSetting;

		private Harmony harmony;

		private readonly Dictionary<Character, AppearanceSnapshot> snapshots = new Dictionary<Character, AppearanceSnapshot>();

		private readonly List<GameObject> attachments = new List<GameObject>();

		internal readonly Dictionary<ThornOnMe, ThornOrigin> thornOrigins = new Dictionary<ThornOnMe, ThornOrigin>();

		private void Awake()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			Instance = this;
			enabledSetting = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Preserve equipment visuals in the ending cinematic.");
			KeepThorns = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "ArrowsAndThorns", true, "Show arrows and thorns still stuck in each character.");
			KeepHeldItem = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "HeldItem", true, "Show the item held when the cinematic starts.");
			KeepBackpack = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "Backpack", true, "Show the worn backpack and its existing item visuals.");
			KeepTicks = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "Ticks", true, "Show attached ticks at their current size.");
			KeepStickyItems = ((BaseUnityPlugin)this).Config.Bind<bool>("Visuals", "StickyItems", true, "Show cactus balls and other items stuck to the character.");
			harmony = new Harmony("ritsukage.peak.endingkeepsakes");
			harmony.PatchAll();
			SceneManager.sceneUnloaded += OnSceneUnloaded;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ending Keepsakes 1.0.0 loaded. Ending appearance patches installed.");
		}

		internal void CaptureAll()
		{
			ClearEnding();
			if (!enabledSetting.Value)
			{
				return;
			}
			Character[] array = Character.AllCharacters.ToArray();
			foreach (Character val in array)
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					try
					{
						AppearanceSnapshot appearanceSnapshot = AppearanceSnapshot.Capture(val);
						snapshots.Add(val, appearanceSnapshot);
						LogInfo($"Captured character {((Object)val).GetInstanceID()}: {appearanceSnapshot.Summary}");
					}
					catch (Exception ex)
					{
						Warn("Capture failed for one character: " + ex);
					}
				}
			}
		}

		internal void Apply(Character character, CustomizationRefs target)
		{
			if (enabledSetting.Value && Object.op_Implicit((Object)(object)character) && Object.op_Implicit((Object)(object)target) && snapshots.TryGetValue(character, out var value))
			{
				KeepsakeMarker[] componentsInChildren = ((Component)target).GetComponentsInChildren<KeepsakeMarker>(true);
				foreach (KeepsakeMarker obj in componentsInChildren)
				{
					((Component)obj).gameObject.SetActive(false);
					Object.Destroy((Object)(object)((Component)obj).gameObject);
				}
				AppearanceSnapshot.AttachResult attachResult = value.Attach(((Component)target).transform, Object.op_Implicit((Object)(object)target.mainRenderer) ? ((Component)target.mainRenderer).gameObject.layer : ((Component)target).gameObject.layer);
				attachments.AddRange(attachResult.Roots);
				LogInfo($"Applied to {((Object)target).name}: meshes={attachResult.Meshes}, missingBones={attachResult.MissingBones}");
			}
		}

		private void ClearEnding()
		{
			foreach (GameObject attachment in attachments)
			{
				if (Object.op_Implicit((Object)(object)attachment))
				{
					attachment.SetActive(false);
					Object.Destroy((Object)(object)attachment);
				}
			}
			attachments.Clear();
			foreach (AppearanceSnapshot value in snapshots.Values)
			{
				value.Dispose();
			}
			snapshots.Clear();
		}

		private void OnSceneUnloaded(Scene scene)
		{
			ClearEnding();
			ThornOnMe[] array = thornOrigins.Keys.Where((ThornOnMe t) => !Object.op_Implicit((Object)(object)t)).ToArray();
			foreach (ThornOnMe key in array)
			{
				thornOrigins.Remove(key);
			}
		}

		private void OnDestroy()
		{
			SceneManager.sceneUnloaded -= OnSceneUnloaded;
			ClearEnding();
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal static void LogInfo(string text)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)text);
		}

		internal static void Warn(string text)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)text);
		}
	}
	public sealed class KeepsakeMarker : MonoBehaviour
	{
	}
	internal sealed class ThornOrigin
	{
		internal readonly Transform Parent;

		internal readonly Matrix4x4 Local;

		internal ThornOrigin(Transform thorn)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			Parent = thorn.parent;
			Local = Matrix4x4.TRS(thorn.localPosition, thorn.localRotation, thorn.localScale);
		}
	}
}