Decompiled source of UCustomPrefabs ContentWarning v0.0.4

BepInEx/plugins/UCustomPrefabs/UCustomPrefabsAPI.ContentWarning.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using Steamworks;
using TMPro;
using UCustomPrefabsAPI.ContentWarning.CustomActions;
using UCustomPrefabsAPI.ContentWarning.Networking;
using UCustomPrefabsAPI.ContentWarning.Patches.Mirror;
using UCustomPrefabsAPI.Extras.Animation;
using UCustomPrefabsAPI.Extras.AssetBundles;
using UCustomPrefabsAPI.Extras.CustomActions;
using UCustomPrefabsAPI.Extras.Utility;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 UCustomPrefabsAPI.ContentWarning
{
	public static class PluginInfo
	{
		public const string GUID = "UCustomPrefabsAPI.ContentWarning";

		public const string NAME = "UCustomPrefabsAPI.ContentWarning";

		public const string VERSION = "0.0.4";

		public const string WEBSITE = "https://github.com/ScottyFox/UCustomPrefabsAPI";
	}
	[BepInPlugin("UCustomPrefabsAPI.ContentWarning", "UCustomPrefabsAPI.ContentWarning", "0.0.4")]
	public class Plugin : BaseUnityPlugin
	{
		public static ConfigFile config;

		public static ConfigEntry<bool> UseMirrorSelector;

		public static ConfigEntry<string> TemplatesAssetBundlesPath;

		public static ConfigEntry<string> TemplatesFileFinderName;

		public static ConfigEntry<string> localPlayerConfig;

		internal static Harmony instance = new Harmony("UCustomPrefabsAPI.ContentWarning");

		private void Awake()
		{
			try
			{
				SetUpConfig();
				RegisterAssetBundles();
				RegisterCustomActions();
				RegisterCustomTemplates();
				BulkLoadTemplates();
				instance.PatchAll(Assembly.GetExecutingAssembly());
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin UCustomPrefabsAPI.ContentWarning is loaded!");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin UCustomPrefabsAPI.ContentWarning failed to load...");
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		public void SetUpConfig()
		{
			config = ((BaseUnityPlugin)this).Config;
			UseMirrorSelector = config.Bind<bool>("ContentWarning Extras", "Use Mirror Selector", true, (ConfigDescription)null);
			TemplatesAssetBundlesPath = config.Bind<string>("UCustomPrefabs Paths", "Templates Folder", "Templates/", (ConfigDescription)null);
			TemplatesFileFinderName = config.Bind<string>("UCustomPrefabs Paths", "Templates Folder Finder File", "ucustomprefabs.templates.txt", (ConfigDescription)null);
			localPlayerConfig = config.Bind<string>("Player Config", "Current Template(s)", "", (ConfigDescription)null);
		}

		public static void RegisterAssetBundles()
		{
			AssetBundleRegistry.RegisterEmbedded<Plugin>("Assets/mirrorselector", "CW_MirrorSelector_AssetBundle");
		}

		public static void RegisterCustomActions()
		{
			CustomActionsRegistry.Register<CW_RigHelper>("CW_RigHelper");
			CustomActionsRegistry.Register<CW_ShaderFix>("CW_ShaderFix");
			CustomActionsRegistry.Register<CW_VisorHelper>("CW_VisorHelper");
			CustomActionsRegistry.Register<CW_VisorTextHelper>("CW_VisorTextHelper");
			CustomActionsRegistry.Register<CW_MirrorSelector>("CW_MirrorDebugSelector");
		}

		public static void RegisterCustomTemplates()
		{
			TemplateRegistry.Register("CW_MirrorSelector", AssetBundleRegistry.LoadPrefab("CW_MirrorSelector_AssetBundle", "mirrortest"));
		}

		public static void BulkLoadTemplates()
		{
			foreach (string item in UCustomPrefabFileHelper.FindDirectoriesWithFileName(Paths.PluginPath, TemplatesFileFinderName.Value))
			{
				UCustomPrefabFileHelper.TryToLoadTemplateAssetBundlesFromPath<Plugin>(item);
			}
		}
	}
	[HarmonyPatch]
	internal static class PlayerPatch
	{
		[HarmonyPatch(typeof(Player), "DoInits")]
		[HarmonyPostfix]
		private static void DoInits_Postfix_Patch(ref Player __instance)
		{
			if (CW_Utilities.IsPlayer(__instance))
			{
				((Component)__instance).gameObject.AddComponent<PlayerConfigHelper>();
			}
		}
	}
	public static class CW_Utilities
	{
		public static bool IsPlayer(Player player)
		{
			return PlayerHandler.instance.players.Contains(player);
		}

		public static bool TryGetPlayerWithSteamID(CSteamID steamID, out Player player)
		{
			//IL_0027: 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)
			player = null;
			if (Object.op_Implicit((Object)(object)PlayerHandler.instance))
			{
				Player[] playerList = PhotonNetwork.PlayerList;
				CSteamID val2 = default(CSteamID);
				foreach (Player val in playerList)
				{
					if (!SteamAvatarHandler.TryGetSteamIDForPlayer(val, ref val2) || !(val2 == steamID))
					{
						continue;
					}
					foreach (Player player2 in PlayerHandler.instance.players)
					{
						if (val.ActorNumber == ((MonoBehaviourPun)player2).photonView.OwnerActorNr)
						{
							player = player2;
							return true;
						}
					}
				}
			}
			return false;
		}

		public static bool TryGetSteamIDWithPlayer(Player player, out CSteamID steamID)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			steamID = default(CSteamID);
			if (Object.op_Implicit((Object)(object)player))
			{
				Player[] playerList = PhotonNetwork.PlayerList;
				foreach (Player val in playerList)
				{
					if (val.ActorNumber == ((MonoBehaviourPun)player).photonView.OwnerActorNr)
					{
						return SteamAvatarHandler.TryGetSteamIDForPlayer(val, ref steamID);
					}
				}
			}
			return false;
		}

		public static bool TryGetPlayerWithActorNumber(int actorNumber, out Player player)
		{
			player = null;
			foreach (Player player2 in PlayerHandler.instance.players)
			{
				if (((MonoBehaviourPun)player2).photonView.OwnerActorNr == actorNumber)
				{
					player = player2;
					return true;
				}
			}
			return false;
		}
	}
}
namespace UCustomPrefabsAPI.ContentWarning.Patches
{
	[HarmonyPatch]
	internal class MirrorPatch
	{
		[HarmonyPatch(typeof(PlayerCustomizer), "Awake")]
		[HarmonyPostfix]
		private static void Awake_Postfix_Patch(ref PlayerCustomizer __instance)
		{
			GameObject val = GameObject.Find("Mirror");
			if (Object.op_Implicit((Object)(object)val))
			{
				_ = Plugin.UseMirrorSelector.Value;
				InstanceManager.Register("CW_MirrorSelector", "CW_MirrorSelector", val.transform);
			}
			else
			{
				Debug.Log((object)"Couldnt Find Mirror!");
			}
		}
	}
}
namespace UCustomPrefabsAPI.ContentWarning.Patches.Mirror
{
	public class CW_MirrorSelector : CustomActionsBase
	{
		private string CurrentOption = string.Empty;

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

		private int OptionIndex;

		private TextMeshPro Display;

		private CW_MirrorSelector_Arrow LeftArrow;

		private CW_MirrorSelector_Arrow RightArrow;

		public override void RegisterActions()
		{
			((CustomActionsBase)this).AddOnStateChanged((Action<string, string>)AttachTargets);
		}

		public void AttachTargets(string last, string current)
		{
			TaggedBehaviour tagInTemplates = ((HandlerReferencer)this).Handler.GetTagInTemplates(new string[1] { "Display" });
			TaggedBehaviour tagInTemplates2 = ((HandlerReferencer)this).Handler.GetTagInTemplates(new string[1] { "LeftArrow" });
			TaggedBehaviour tagInTemplates3 = ((HandlerReferencer)this).Handler.GetTagInTemplates(new string[1] { "RightArrow" });
			if ((Object)(object)tagInTemplates == (Object)null || (Object)(object)tagInTemplates2 == (Object)null || (Object)(object)tagInTemplates3 == (Object)null)
			{
				Debug.LogWarning((object)"Unable to setup Mirror Selector.");
				return;
			}
			Display = ((Component)tagInTemplates).GetComponent<TextMeshPro>();
			LeftArrow = ((Component)tagInTemplates2).gameObject.AddComponent<CW_MirrorSelector_Arrow>();
			RightArrow = ((Component)tagInTemplates3).gameObject.AddComponent<CW_MirrorSelector_Arrow>();
			((Component)LeftArrow).gameObject.layer = LayerMask.NameToLayer("Interactable");
			((Component)RightArrow).gameObject.layer = ((Component)LeftArrow).gameObject.layer;
			((Interactable)LeftArrow).hoverText = "Last";
			((Interactable)RightArrow).hoverText = "Next";
			LeftArrow.CustomAction = this;
			RightArrow.CustomAction = this;
			Options = TemplateRegistry.GetTemplatesWithCustomActions<CW_RigHelper>();
			Options.Add("None");
			SwitchToOption(PlayerConfigHelper.GetPlayerData());
			PlayerConfigHelper.SetPlayerData(CurrentOption);
		}

		public void ArrowInteracted(CW_MirrorSelector_Arrow Arrow, Player Player)
		{
			if ((Object)(object)Arrow == (Object)(object)LeftArrow)
			{
				OptionIndex--;
			}
			else if ((Object)(object)Arrow == (Object)(object)RightArrow)
			{
				OptionIndex++;
			}
			if (OptionIndex < 0)
			{
				OptionIndex = Options.Count - 1;
			}
			else if (OptionIndex >= Options.Count)
			{
				OptionIndex = 0;
			}
			UpdateOption(OptionIndex);
			PlayerConfigHelper component = ((Component)Player).GetComponent<PlayerConfigHelper>();
			if ((Object)(object)component != (Object)null)
			{
				PlayerConfigHelper.SetPlayerData(CurrentOption);
				component.UpdatePlayerData();
			}
		}

		public void UpdateOption(int Index)
		{
			if (Index >= 0 && Index < Options.Count && !((Object)(object)Display == (Object)null))
			{
				CurrentOption = Options[Index];
				((TMP_Text)Display).text = CurrentOption;
			}
		}

		public void SwitchToOption(string Option)
		{
			int num = Options.IndexOf(Option);
			if (num == -1)
			{
				UpdateOption(Options.Count - 1);
			}
			else
			{
				UpdateOption(num);
			}
		}
	}
	public class CW_MirrorSelector_Arrow : Interactable
	{
		public CW_MirrorSelector CustomAction;

		public override void Interact(Player player)
		{
			if (CustomAction != null)
			{
				CustomAction.ArrowInteracted(this, player);
			}
		}
	}
}
namespace UCustomPrefabsAPI.ContentWarning.Networking
{
	public class PlayerConfigHelper : MonoBehaviourPunCallbacks
	{
		public const string PlayerDataPrefix = "ucp_pd";

		private string currentConfig = string.Empty;

		public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
			UpdateTemplates(targetPlayer);
		}

		public void UpdatePlayerData()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0028: Expected O, but got Unknown
			if (((MonoBehaviourPun)this).photonView.IsMine)
			{
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)"ucp_pd", (object)Plugin.localPlayerConfig.Value);
				Hashtable val2 = val;
				PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null);
			}
			UpdateTemplates(((MonoBehaviourPun)this).photonView.Owner);
		}

		public static string GetPlayerData()
		{
			return Plugin.localPlayerConfig.Value;
		}

		public static void SetPlayerData(string data)
		{
			Plugin.localPlayerConfig.Value = data;
		}

		public void UpdateTemplates(Player targetPlayer)
		{
			if (targetPlayer != ((MonoBehaviourPun)this).photonView.Owner || !((Dictionary<object, object>)(object)targetPlayer.CustomProperties).TryGetValue((object)"ucp_pd", out object value))
			{
				return;
			}
			string text = (string)value;
			if (!(text == currentConfig) && !string.IsNullOrWhiteSpace(text) && Object.op_Implicit((Object)(object)((Component)((Component)this).transform).GetComponent<Player>()))
			{
				InstanceManager.RemoveInstancesFromTarget(((Component)this).transform);
				string[] array = text.Split(new char[1] { ',' });
				foreach (string text2 in array)
				{
					InstanceManager.Register($"{targetPlayer.ActorNumber}:{text2}", text2, ((Component)this).transform);
				}
				currentConfig = text;
			}
		}

		public void Start()
		{
			UpdatePlayerData();
		}
	}
}
namespace UCustomPrefabsAPI.ContentWarning.CustomActions
{
	public class CW_RigHelper : CustomActionsBase
	{
		private Player player;

		private Dictionary<RigBuilder, BoneRigTracker> Rig_Targets = new Dictionary<RigBuilder, BoneRigTracker>();

		private static LayerMask Layer_LocalDontSee = LayerMask.op_Implicit(LayerMask.NameToLayer("LocalDontSee"));

		public override void RegisterActions()
		{
			((CustomActionsBase)this).AddOnStateChanged((Action<string, string>)AttachTargets);
			((CustomActionsBase)this).AddOnUpdate((Action)Update);
			((CustomActionsBase)this).AddOnDestroy((Action)Reset);
		}

		public void AttachTargets(string last, string state)
		{
			player = ((Component)((HandlerReferencer)this).Handler).GetComponent<Player>();
			if (!Object.op_Implicit((Object)(object)player))
			{
				return;
			}
			HideVanilla(hide: false);
			Transform val = ((Component)player).transform.Find("RigCreator/Rig/Armature");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in ((HandlerReferencer)this).Handler.LoadedTemplates)
			{
				SetUpRig(((Component)loadedTemplate.Value).GetComponent<RigBuilder>(), val);
				RigBuilder[] componentsInChildren = ((Component)loadedTemplate.Value).GetComponentsInChildren<RigBuilder>();
				foreach (RigBuilder rig in componentsInChildren)
				{
					SetUpRig(rig, val);
				}
			}
			HideVanilla(hide: true);
			FixVisuals();
			Update();
		}

		public void Reset()
		{
			HideVanilla(hide: false);
		}

		public void SetUpRig(RigBuilder rig, Transform hips)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			if (Object.op_Implicit((Object)(object)rig) && !Rig_Targets.TryGetValue(rig, out var value))
			{
				value = new BoneRigTracker(((Component)rig).transform, hips);
				value.SetUpRig(rig.Rig, (Transform)null);
				Rig_Targets.Add(rig, value);
			}
		}

		public void HideVanilla(bool hide)
		{
			if (!Object.op_Implicit((Object)(object)((HandlerReferencer)this).Handler))
			{
				return;
			}
			Transform obj = ((Component)((HandlerReferencer)this).Handler).transform.Find("CharacterModel");
			Renderer[] array = ((obj != null) ? ((Component)obj).GetComponentsInChildren<Renderer>() : null);
			if (array != null)
			{
				Renderer[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					array2[i].forceRenderingOff = hide;
				}
			}
			Transform obj2 = ((Component)((HandlerReferencer)this).Handler).transform.Find("HeadPosition/FACE");
			Renderer val = ((obj2 != null) ? ((Component)obj2).GetComponent<Renderer>() : null);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.forceRenderingOff = hide;
			}
		}

		public void FixVisuals()
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			if (((MonoBehaviourPun)player).photonView.IsMine)
			{
				foreach (PrefabTemplate item in ((HandlerReferencer)this).Handler.GetTemplatesWithTag(new string[1] { "LocalDontSee" }))
				{
					Renderer[] componentsInChildren = ((Component)item).GetComponentsInChildren<Renderer>();
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Component)componentsInChildren[i]).gameObject.layer = LayerMask.op_Implicit(Layer_LocalDontSee);
					}
				}
				{
					foreach (TaggedBehaviour tagsInTemplate in ((HandlerReferencer)this).Handler.GetTagsInTemplates(new string[1] { "LocalShinkBone" }))
					{
						((Component)tagsInTemplate).transform.localScale = Vector3.zero;
					}
					return;
				}
			}
			foreach (PrefabTemplate item2 in ((HandlerReferencer)this).Handler.GetTemplatesWithTag(new string[1] { "FirstPersonOnly" }))
			{
				Renderer[] componentsInChildren = ((Component)item2).GetComponentsInChildren<Renderer>();
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					componentsInChildren[i].forceRenderingOff = true;
				}
			}
		}

		public void Update()
		{
			bool flag;
			do
			{
				flag = true;
				foreach (KeyValuePair<RigBuilder, BoneRigTracker> rig_Target in Rig_Targets)
				{
					if (!Object.op_Implicit((Object)(object)rig_Target.Key) || rig_Target.Value == null)
					{
						flag = false;
						break;
					}
					rig_Target.Value.Update();
				}
				if (!flag)
				{
					Verify();
				}
			}
			while (!flag);
		}

		public void Verify()
		{
			Debug.LogWarning((object)"Tracker seems to be invalid, Verifying.");
			Dictionary<RigBuilder, BoneRigTracker> dictionary = new Dictionary<RigBuilder, BoneRigTracker>();
			foreach (KeyValuePair<RigBuilder, BoneRigTracker> rig_Target in Rig_Targets)
			{
				if (Object.op_Implicit((Object)(object)rig_Target.Key) && rig_Target.Value != null)
				{
					dictionary.Add(rig_Target.Key, rig_Target.Value);
				}
				else
				{
					Debug.LogWarning((object)"Removing Tracker from RigHelper!");
				}
			}
			Rig_Targets = dictionary;
		}
	}
	public class CW_ShaderFix : CustomActionsBase
	{
		public override void RegisterActions()
		{
			((CustomActionsBase)this).AddOnStateChanged((Action<string, string>)DoFix);
		}

		public void DoFix(string last, string state)
		{
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in ((HandlerReferencer)this).Handler.LoadedTemplates)
			{
				FixShaders(((Component)loadedTemplate.Value).transform);
			}
		}

		public void FixShaders(Transform target)
		{
			Renderer[] componentsInChildren = ((Component)target).GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Shader val2 = Shader.Find(((Object)sharedMaterials[j].shader).name);
					if ((Object)(object)val2 != (Object)null)
					{
						sharedMaterials[j].shader = val2;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
		}
	}
	public class CW_VisorHelper : CustomActionsBase
	{
		private Player Player;

		private Dictionary<Renderer, List<int>> Renderer_Targets = new Dictionary<Renderer, List<int>>();

		private MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();

		public override void RegisterActions()
		{
			((CustomActionsBase)this).AddOnStateChanged((Action<string, string>)AttachTargets);
			((CustomActionsBase)this).AddOnUpdate((Action)Update);
		}

		public void AttachTargets(string last, string current)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			Player = ((Component)((HandlerReferencer)this).Handler).GetComponent<Player>();
			if (!Object.op_Implicit((Object)(object)Player))
			{
				return;
			}
			Material currentVisorMaterial = GetCurrentVisorMaterial();
			string text = default(string);
			foreach (TaggedBehaviour tagsInTemplate in ((HandlerReferencer)this).Handler.GetTagsInTemplates(new string[1] { "UseVanillaVisor" }))
			{
				TaggedData component = ((Component)tagsInTemplate).GetComponent<TaggedData>();
				Renderer component2 = ((Component)tagsInTemplate).GetComponent<Renderer>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2) || !component.TryGetTagData("UseVanillaVisor", ref text))
				{
					continue;
				}
				Material[] sharedMaterials = component2.sharedMaterials;
				string[] array = text.Split(new char[1] { ',' });
				for (int i = 0; i < array.Length; i++)
				{
					if (int.TryParse(array[i], out var result) && result >= 0 && result < sharedMaterials.Length)
					{
						sharedMaterials[result] = new Material(currentVisorMaterial);
						if (!Renderer_Targets.TryGetValue(component2, out var value))
						{
							value = new List<int>();
							Renderer_Targets.Add(component2, value);
						}
						value.Add(result);
					}
				}
				component2.sharedMaterials = sharedMaterials;
			}
			string text2 = default(string);
			foreach (TaggedBehaviour tagsInTemplate2 in ((HandlerReferencer)this).Handler.GetTagsInTemplates(new string[1] { "UseCustomVisor" }))
			{
				TaggedData component3 = ((Component)tagsInTemplate2).GetComponent<TaggedData>();
				Renderer component4 = ((Component)tagsInTemplate2).GetComponent<Renderer>();
				if (!Object.op_Implicit((Object)(object)component3) || !Object.op_Implicit((Object)(object)component4) || !component3.TryGetTagData("UseCustomVisor", ref text2))
				{
					continue;
				}
				Material[] sharedMaterials2 = component4.sharedMaterials;
				string[] array = text2.Split(new char[1] { ',' });
				for (int i = 0; i < array.Length; i++)
				{
					if (int.TryParse(array[i], out var result2) && result2 >= 0 && result2 < sharedMaterials2.Length)
					{
						if (!Renderer_Targets.TryGetValue(component4, out var value2))
						{
							value2 = new List<int>();
							Renderer_Targets.Add(component4, value2);
						}
						value2.Add(result2);
					}
				}
			}
			Update();
		}

		public void Verify()
		{
			Debug.LogWarning((object)"Visor Renderer seems to be invalid, Verifying.");
			Dictionary<Renderer, List<int>> dictionary = new Dictionary<Renderer, List<int>>();
			foreach (KeyValuePair<Renderer, List<int>> renderer_Target in Renderer_Targets)
			{
				if (Object.op_Implicit((Object)(object)renderer_Target.Key))
				{
					dictionary.Add(renderer_Target.Key, renderer_Target.Value);
				}
				else
				{
					Debug.LogWarning((object)"Removing Renderer from VisorHelper!");
				}
			}
			Renderer_Targets = dictionary;
		}

		public void Update()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Player))
			{
				return;
			}
			Material currentVisorMaterial = GetCurrentVisorMaterial();
			propertyBlock.SetColor("_Color", currentVisorMaterial.GetColor("_Color"));
			propertyBlock.SetFloat("_VoiceEmis", currentVisorMaterial.GetFloat("_VoiceEmis"));
			propertyBlock.SetFloat("_Voice", currentVisorMaterial.GetFloat("_Voice"));
			propertyBlock.SetFloat("_M1", currentVisorMaterial.GetFloat("_M1"));
			propertyBlock.SetFloat("_M2", currentVisorMaterial.GetFloat("_M2"));
			propertyBlock.SetFloat("_TextureStrength", currentVisorMaterial.GetFloat("_TextureStrength"));
			propertyBlock.SetFloat("_TextureStrength2", currentVisorMaterial.GetFloat("_TextureStrength2"));
			bool flag;
			do
			{
				flag = true;
				foreach (KeyValuePair<Renderer, List<int>> renderer_Target in Renderer_Targets)
				{
					if (!Object.op_Implicit((Object)(object)renderer_Target.Key))
					{
						flag = false;
						break;
					}
					foreach (int item in renderer_Target.Value)
					{
						renderer_Target.Key.SetPropertyBlock(propertyBlock, item);
					}
				}
				if (!flag)
				{
					Verify();
				}
			}
			while (!flag);
		}

		public void UpdateVisorPropertyBlock()
		{
			Player.refs.visor.visorRenderer.GetPropertyBlock(propertyBlock, Player.refs.visor.visorMaterialIndex);
		}

		public Color GetCurrentVisorColor()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return GetCurrentVisorMaterial().GetColor("_Color");
		}

		public Material GetCurrentVisorMaterial()
		{
			return Player.refs.visor.visorRenderer.sharedMaterials[Player.refs.visor.visorMaterialIndex];
		}
	}
	public class CW_VisorTextHelper : CustomActionsBase
	{
		private const float CW_Visor_MaxSize = 0.04f;

		private Player Player;

		private HashSet<TextMeshPro> TextMeshPro_Targets = new HashSet<TextMeshPro>();

		private string Text = string.Empty;

		private float Rotation;

		private float FaceSize = 1f;

		public override void RegisterActions()
		{
			((CustomActionsBase)this).AddOnStateChanged((Action<string, string>)AttachTargets);
			((CustomActionsBase)this).AddOnUpdate((Action)Update);
		}

		public void AttachTargets(string last, string current)
		{
			Player = ((Component)((HandlerReferencer)this).Handler).GetComponent<Player>();
			if (!Object.op_Implicit((Object)(object)Player))
			{
				return;
			}
			foreach (TaggedBehaviour tagsInTemplate in ((HandlerReferencer)this).Handler.GetTagsInTemplates(new string[1] { "UseVisorText" }))
			{
				TextMeshPro component = ((Component)tagsInTemplate).GetComponent<TextMeshPro>();
				if (Object.op_Implicit((Object)(object)component))
				{
					FixTextOffsets(component);
					TextMeshPro_Targets.Add(component);
				}
			}
			Update();
		}

		public void FixTextOffsets(TextMeshPro target)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if (!(((Transform)((TMP_Text)target).rectTransform).localScale == Vector3.one) || !(((Transform)((TMP_Text)target).rectTransform).localRotation == Quaternion.identity))
			{
				GameObject val = new GameObject(((Object)target).name + "(Container)");
				val.transform.SetParent(target.transform.parent);
				val.transform.localPosition = target.transform.localPosition;
				val.transform.localScale = target.transform.localScale;
				val.transform.localRotation = target.transform.localRotation;
				target.transform.SetParent(val.transform);
				target.transform.localPosition = Vector3.zero;
				target.transform.localScale = Vector3.one;
				target.transform.localRotation = Quaternion.identity;
			}
		}

		public void Verify()
		{
			Debug.LogWarning((object)"VisorText seems to be invalid, Verifying.");
			HashSet<TextMeshPro> hashSet = new HashSet<TextMeshPro>();
			foreach (TextMeshPro textMeshPro_Target in TextMeshPro_Targets)
			{
				if (Object.op_Implicit((Object)(object)textMeshPro_Target))
				{
					hashSet.Add(textMeshPro_Target);
				}
				else
				{
					Debug.LogWarning((object)"Removing TextMeshPro from VisorTextHelper!");
				}
			}
			TextMeshPro_Targets = hashSet;
		}

		public void Update()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)Player))
			{
				return;
			}
			PlayerVisor visor = Player.refs.visor;
			if (visor.visorFaceText.transform.localEulerAngles.z == Rotation && visor.FaceSize == FaceSize && ((TMP_Text)visor.visorFaceText).text == Text)
			{
				return;
			}
			Rotation = visor.visorFaceText.transform.localEulerAngles.z;
			FaceSize = visor.FaceSize;
			Text = ((TMP_Text)visor.visorFaceText).text;
			Vector3 localScale = Vector3.one * (FaceSize / 0.04f);
			Vector3 localEulerAngles = default(Vector3);
			((Vector3)(ref localEulerAngles))..ctor(0f, 0f, Rotation);
			bool flag;
			do
			{
				flag = true;
				foreach (TextMeshPro textMeshPro_Target in TextMeshPro_Targets)
				{
					if (!Object.op_Implicit((Object)(object)textMeshPro_Target))
					{
						flag = false;
						break;
					}
					((Transform)((TMP_Text)textMeshPro_Target).rectTransform).localEulerAngles = localEulerAngles;
					((Transform)((TMP_Text)textMeshPro_Target).rectTransform).localScale = localScale;
					((TMP_Text)textMeshPro_Target).text = Text;
				}
				if (!flag)
				{
					Verify();
				}
			}
			while (!flag);
		}
	}
	public class CW_RigHelperTemplate : CustomActionsTemplate
	{
		public override Type RegisterCustomActionsBaseType()
		{
			return typeof(CW_RigHelper);
		}
	}
	public class CW_ShaderFixTemplate : CustomActionsTemplate
	{
		public override Type RegisterCustomActionsBaseType()
		{
			return typeof(CW_ShaderFix);
		}
	}
	public class CW_VisorHelperTemplate : CustomActionsTemplate
	{
		public override Type RegisterCustomActionsBaseType()
		{
			return typeof(CW_VisorHelper);
		}
	}
	public class CW_VisorTextHelperTemplate : CustomActionsTemplate
	{
		public override Type RegisterCustomActionsBaseType()
		{
			return typeof(CW_VisorTextHelper);
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}

BepInEx/plugins/UCustomPrefabs/UCustomPrefabsAPI.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using Microsoft.CodeAnalysis;
using UCustomPrefabsAPI.Extras.AssetBundles;
using UCustomPrefabsAPI.Extras.CustomActions;
using UCustomPrefabsAPI.Extras.Utility;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.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 UCustomPrefabsAPI
{
	public class ActionStateMachine
	{
		private class StateActions
		{
			public List<Action<string>> OnEnter = new List<Action<string>>();

			public List<Action> OnUpdate = new List<Action>();

			public List<Action<string>> OnExit = new List<Action<string>>();
		}

		private Dictionary<string, StateActions> _StatesActions = new Dictionary<string, StateActions>();

		private List<Action<string, string>> OnStateChanged = new List<Action<string, string>>();

		private List<Action> OnUpdate = new List<Action>();

		private List<Action> OnDestroy = new List<Action>();

		private StateActions _CurrentActions;

		public string State { get; private set; } = string.Empty;


		public bool HasState(string name)
		{
			return _StatesActions.ContainsKey(name);
		}

		public void AddState(string name)
		{
			Internal_AddState(name);
		}

		private StateActions Internal_AddState(string name, bool addState = true)
		{
			if (!_StatesActions.TryGetValue(name, out var value) && addState)
			{
				value = new StateActions();
				_StatesActions.Add(name, value);
			}
			return value;
		}

		public void AddOnEnter(string name, Action<string> action, bool addState = false)
		{
			Internal_AddState(name, addState)?.OnEnter.Add(action);
		}

		public void AddOnUpdate(string name, Action action, bool addState = false)
		{
			Internal_AddState(name, addState)?.OnUpdate.Add(action);
		}

		public void AddOnExit(string name, Action<string> action, bool addState = false)
		{
			Internal_AddState(name, addState)?.OnExit.Add(action);
		}

		public void AddOnStateChanged(Action<string, string> action)
		{
			OnStateChanged.Add(action);
		}

		public void AddOnUpdate(Action action)
		{
			OnUpdate.Add(action);
		}

		public void AddOnDestroy(Action action)
		{
			OnDestroy.Add(action);
		}

		public void Do_OnEnter()
		{
			_CurrentActions?.OnEnter.ForEach(delegate(Action<string> action)
			{
				try
				{
					action?.Invoke(State);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			});
		}

		public void Do_OnExit()
		{
			_CurrentActions?.OnExit.ForEach(delegate(Action<string> action)
			{
				try
				{
					action?.Invoke(State);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			});
		}

		public void Do_OnStateChanged(string lastState)
		{
			OnStateChanged.ForEach(delegate(Action<string, string> action)
			{
				try
				{
					action?.Invoke(lastState, State);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			});
		}

		public void SetState(string name)
		{
			if (!(State == name))
			{
				_StatesActions.TryGetValue(name, out _CurrentActions);
				State = name;
			}
		}

		public void Update()
		{
			_CurrentActions?.OnUpdate.ForEach(delegate(Action action)
			{
				action?.Invoke();
			});
			OnUpdate.ForEach(delegate(Action action)
			{
				try
				{
					action?.Invoke();
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			});
		}

		public void Destroy()
		{
			OnDestroy.ForEach(delegate(Action action)
			{
				try
				{
					action?.Invoke();
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			});
		}
	}
	public abstract class CustomActionsBase : HandlerReferencer, IComparable<CustomActionsBase>
	{
		private ActionStateMachine StateMachine => base.Handler?.StateMachine;

		public int Priority { get; set; }

		public void AddOnEnter(string name, Action<string> action, bool addState = false)
		{
			StateMachine.AddOnEnter(name, action, addState);
		}

		public void AddOnUpdate(string name, Action action, bool addState = false)
		{
			StateMachine.AddOnUpdate(name, action, addState);
		}

		public void AddOnExit(string name, Action<string> action, bool addState = false)
		{
			StateMachine.AddOnExit(name, action, addState);
		}

		public void AddOnStateChanged(Action<string, string> action)
		{
			StateMachine.AddOnStateChanged(action);
		}

		public void AddOnUpdate(Action action)
		{
			StateMachine.AddOnUpdate(action);
		}

		public void AddOnDestroy(Action action)
		{
			StateMachine.AddOnDestroy(action);
		}

		public abstract void RegisterActions();

		public virtual void HandleTemplateData(object[] data)
		{
		}

		public int CompareTo(CustomActionsBase other)
		{
			return Priority.CompareTo(other.Priority);
		}
	}
	public static class UCustomPrefabFileHelper
	{
		public static List<string> FindDirectoriesWithFileName(string path, string fileName)
		{
			List<string> list = new List<string>();
			Queue<string> queue = new Queue<string>();
			queue.Enqueue(path);
			while (queue.Count > 0)
			{
				string text = queue.Dequeue();
				try
				{
					if (File.Exists(Path.Combine(text, fileName)))
					{
						list.Add(text);
					}
					string[] directories = Directory.GetDirectories(text);
					foreach (string item in directories)
					{
						queue.Enqueue(item);
					}
				}
				catch (Exception ex)
				{
					Debug.LogError((object)("Unable to Access " + text));
					Debug.LogError((object)ex);
				}
			}
			return list;
		}

		private static bool IsAssetBundle(string path)
		{
			bool result = false;
			try
			{
				using FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read);
				using BinaryReader binaryReader = new BinaryReader(input);
				byte[] bytes = binaryReader.ReadBytes(8);
				string @string = Encoding.ASCII.GetString(bytes);
				if (@string.StartsWith("UnityFS") || @string.StartsWith("UnityRaw") || @string.StartsWith("UnityWeb"))
				{
					result = true;
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine("Error Reading File : " + ex.Message);
			}
			return result;
		}

		public static void TryToLoadTemplateAssetBundlesFromPath<T>(string path)
		{
			try
			{
				string[] files = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(typeof(T).Assembly.Location), path));
				List<string> list = new List<string>();
				string[] array = files;
				foreach (string path2 in array)
				{
					if (IsAssetBundle(path2))
					{
						list.Add(Path.Combine(path, Path.GetFileName(path2)));
					}
				}
				foreach (string item in list)
				{
					if (AssetBundleRegistry.Register<T>(item, out var name))
					{
						if (!TryToLoadTemplatesFromAssetBundle(name))
						{
							Debug.Log((object)("Unable to load Templates from Assetbundle : " + name));
							AssetBundleRegistry.Remove(name, unloadAllLoadedObjects: true);
						}
						else
						{
							Debug.Log((object)("Unable to Register AssetBundle : " + item));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Debug.Log((object)("Unable To Access Path : " + path));
				Debug.LogError((object)ex);
			}
		}

		public static bool TryToLoadTemplatesFromAssetBundle(string assetBundleName)
		{
			TextAsset val = AssetBundleRegistry.LoadAsset<TextAsset>(assetBundleName, "templates.ucp.txt");
			if ((Object)(object)val == (Object)null || string.IsNullOrWhiteSpace(val.text))
			{
				Debug.Log((object)("Unable to Read Templates Json from " + assetBundleName));
				return false;
			}
			UCustomPrefab_AssetBundle_TemplatesJSON uCustomPrefab_AssetBundle_TemplatesJSON = new UCustomPrefab_AssetBundle_TemplatesJSON();
			JsonUtility.FromJsonOverwrite(val.text, (object)uCustomPrefab_AssetBundle_TemplatesJSON);
			if (!uCustomPrefab_AssetBundle_TemplatesJSON.Verify())
			{
				Debug.Log((object)"Templates Data is Invalid!");
				return false;
			}
			for (int i = 0; i < uCustomPrefab_AssetBundle_TemplatesJSON.Template_Names.Count; i++)
			{
				GameObject val2 = AssetBundleRegistry.LoadPrefab(assetBundleName, uCustomPrefab_AssetBundle_TemplatesJSON.Template_Prefabs[i]);
				if (!((Object)(object)val2 == (Object)null))
				{
					TemplateRegistry.Register(uCustomPrefab_AssetBundle_TemplatesJSON.Template_Names[i], val2);
				}
			}
			return true;
		}
	}
	[Serializable]
	public class UCustomPrefab_AssetBundle_TemplatesJSON
	{
		public string Name;

		public string Author;

		public string Description;

		public List<string> Template_Names = new List<string>();

		public List<string> Template_Prefabs = new List<string>();

		public bool Verify()
		{
			if (!string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(Author) && !string.IsNullOrWhiteSpace(Description) && Template_Names.Count != 0)
			{
				return Template_Prefabs.Count != 0;
			}
			return false;
		}
	}
	public class InstanceInfo
	{
		public string ID { get; private set; } = string.Empty;


		public Transform Target { get; private set; }

		public string TemplateUID { get; private set; } = string.Empty;


		public UCustomPrefabHandler Handler { get; private set; }

		public InstanceInfo(string id, string template_uid)
		{
			ID = id;
			TemplateUID = template_uid;
		}

		public bool SetTarget(Transform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				Debug.LogWarning((object)"Target Doesn't Exist!");
				return false;
			}
			Target = target;
			Reset();
			return true;
		}

		public bool IsValid()
		{
			if ((Object)(object)Handler != (Object)null)
			{
				return (Object)(object)Target != (Object)null;
			}
			return false;
		}

		public void Reset()
		{
			if ((Object)(object)Target == (Object)null || DestroyHandler())
			{
				return;
			}
			try
			{
				Handler = ((Component)Target).gameObject.AddComponent<UCustomPrefabHandler>();
				Handler.Instance = this;
				Handler.Initialize();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex);
			}
		}

		public bool DestroyHandler(bool reset = true, bool destroy = true)
		{
			if ((Object)(object)Handler == (Object)null)
			{
				return false;
			}
			UCustomPrefabHandler handler = Handler;
			Handler = null;
			if (destroy)
			{
				handler.HandleDestroy(reset);
			}
			return true;
		}

		public void PrepareRemove()
		{
			DestroyHandler(reset: false);
		}
	}
	public static class InstanceManager
	{
		private static Dictionary<string, InstanceInfo> Instances = new Dictionary<string, InstanceInfo>();

		public static bool TryGetInstance(string uid, out InstanceInfo instance)
		{
			instance = null;
			if (string.IsNullOrWhiteSpace(uid))
			{
				return false;
			}
			Verify();
			if (Instances.TryGetValue(uid, out instance))
			{
				return instance != null;
			}
			return false;
		}

		public static InstanceInfo[] GetInstancesInTarget(Transform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return new InstanceInfo[0];
			}
			UCustomPrefabHandler[] components = ((Component)target).gameObject.GetComponents<UCustomPrefabHandler>();
			InstanceInfo[] array = new InstanceInfo[components.Length];
			for (int i = 0; i < components.Length; i++)
			{
				array[i] = components[i]?.Instance;
			}
			return array;
		}

		public static InstanceInfo[] GetInstancesInTargetChildren(Transform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return new InstanceInfo[0];
			}
			UCustomPrefabHandler[] componentsInChildren = ((Component)target).gameObject.GetComponentsInChildren<UCustomPrefabHandler>();
			InstanceInfo[] array = new InstanceInfo[componentsInChildren.Length];
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				array[i] = componentsInChildren[i]?.Instance;
			}
			return array;
		}

		public static InstanceInfo[] GetInstancesInTargetParent(Transform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				return new InstanceInfo[0];
			}
			UCustomPrefabHandler[] componentsInParent = ((Component)target).gameObject.GetComponentsInParent<UCustomPrefabHandler>();
			InstanceInfo[] array = new InstanceInfo[componentsInParent.Length];
			for (int i = 0; i < componentsInParent.Length; i++)
			{
				array[i] = componentsInParent[i]?.Instance;
			}
			return array;
		}

		public static bool Register(string uid, string template_uid, Transform target)
		{
			if (string.IsNullOrWhiteSpace(uid) || string.IsNullOrWhiteSpace(template_uid) || (Object)(object)target == (Object)null)
			{
				return false;
			}
			Verify();
			if (Instances.ContainsKey(uid))
			{
				return false;
			}
			InstanceInfo instanceInfo = new InstanceInfo(uid, template_uid);
			if (!instanceInfo.SetTarget(target))
			{
				return false;
			}
			Instances.Add(uid, instanceInfo);
			return true;
		}

		public static void Verify()
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, InstanceInfo> instance in Instances)
			{
				if (instance.Value == null || !instance.Value.IsValid())
				{
					list.Add(instance.Key);
				}
			}
			foreach (string item in list)
			{
				Remove(item);
			}
		}

		public static void RemoveInstancesFromTarget(Transform target)
		{
			InstanceInfo[] instancesInTarget = GetInstancesInTarget(target);
			for (int i = 0; i < instancesInTarget.Length; i++)
			{
				Remove(instancesInTarget[i]?.ID);
			}
		}

		public static void RemoveInstancesFromTargetChildren(Transform target)
		{
			InstanceInfo[] instancesInTargetChildren = GetInstancesInTargetChildren(target);
			for (int i = 0; i < instancesInTargetChildren.Length; i++)
			{
				Remove(instancesInTargetChildren[i]?.ID);
			}
		}

		public static void RemoveInstancesFromTargetParent(Transform target)
		{
			InstanceInfo[] instancesInTargetParent = GetInstancesInTargetParent(target);
			for (int i = 0; i < instancesInTargetParent.Length; i++)
			{
				Remove(instancesInTargetParent[i]?.ID);
			}
		}

		public static void Remove(string uid)
		{
			if (!string.IsNullOrWhiteSpace(uid) && Instances.TryGetValue(uid, out var value))
			{
				value?.PrepareRemove();
				Instances.Remove(uid);
			}
		}

		public static void ResetInstance(string uid)
		{
			if (!string.IsNullOrWhiteSpace(uid) && Instances.TryGetValue(uid, out var value))
			{
				value?.Reset();
			}
		}

		public static void Reset()
		{
			foreach (string item in new List<string>(Instances.Keys))
			{
				Remove(item);
			}
			Instances.Clear();
		}
	}
	public class InstanceReferencer
	{
		private WeakReference<InstanceInfo> _Instance_Reference = new WeakReference<InstanceInfo>(null);

		public InstanceInfo Instance
		{
			get
			{
				_Instance_Reference.TryGetTarget(out var target);
				return target;
			}
			set
			{
				_Instance_Reference.SetTarget(value);
			}
		}
	}
	public class HandlerReferencer
	{
		private WeakReference<UCustomPrefabHandler> _Handler_Reference = new WeakReference<UCustomPrefabHandler>(null);

		public UCustomPrefabHandler Handler
		{
			get
			{
				_Handler_Reference.TryGetTarget(out var target);
				return target;
			}
			set
			{
				_Handler_Reference.SetTarget(value);
			}
		}
	}
	public class UCustomPrefabHandler : MonoBehaviour
	{
		private InstanceReferencer _instanceReferencer = new InstanceReferencer();

		private Dictionary<Type, CustomActionsBase> RegisteredCustomActions = new Dictionary<Type, CustomActionsBase>();

		private Dictionary<string, Dictionary<string, PrefabTemplate>> Templates = new Dictionary<string, Dictionary<string, PrefabTemplate>>();

		private bool IsDestroyed;

		public InstanceInfo Instance
		{
			get
			{
				return _instanceReferencer.Instance;
			}
			set
			{
				_instanceReferencer.Instance = value;
			}
		}

		public ActionStateMachine StateMachine { get; private set; } = new ActionStateMachine();


		public Dictionary<string, PrefabTemplate> LoadedTemplates { get; private set; } = new Dictionary<string, PrefabTemplate>();


		public void Initialize()
		{
			AddState("init");
			AddState("default");
			RegisterTemplate();
			InitializeAndRegisterCustomActions();
			SetState("default");
		}

		public void SetState(string name, bool reset = true)
		{
			string state = StateMachine.State;
			StateMachine.Do_OnExit();
			ResetTemplates();
			InstantiateStateTemplates(name);
			StateMachine.SetState(name);
			StateMachine.Do_OnEnter();
			StateMachine.Do_OnStateChanged(state);
		}

		public void AddState(string name)
		{
			if (!StateMachine.HasState(name))
			{
				StateMachine.AddState(name);
				Templates.Add(name, new Dictionary<string, PrefabTemplate>());
			}
		}

		public bool TryGetCustomActions<T>(out T customActions) where T : CustomActionsBase
		{
			customActions = null;
			if (RegisteredCustomActions.TryGetValue(typeof(T), out var value))
			{
				customActions = (T)value;
			}
			return customActions != null;
		}

		public T RegisterCustomActions<T>(object[] data = null, int priority = -1) where T : CustomActionsBase
		{
			return (T)RegisterCustomActions(typeof(T), data, priority);
		}

		public CustomActionsBase RegisterCustomActions(Type type, object[] data = null, int priority = -1)
		{
			if (RegisteredCustomActions.TryGetValue(type, out var value))
			{
				return value;
			}
			value = (CustomActionsBase)Activator.CreateInstance(type);
			if (value == null)
			{
				return null;
			}
			value.Priority = priority;
			value.HandleTemplateData(data);
			RegisteredCustomActions.Add(type, value);
			return value;
		}

		public void InitializeAndRegisterCustomActions()
		{
			foreach (KeyValuePair<Type, CustomActionsBase> item in RegisteredCustomActions.OrderBy((KeyValuePair<Type, CustomActionsBase> x) => x.Value.Priority))
			{
				CustomActionsBase value = item.Value;
				value.Handler = this;
				value.RegisterActions();
			}
		}

		public void RegisterTemplate()
		{
			if (Instance == null || !TemplateRegistry.TryGetTemplate(Instance.TemplateUID, out var template))
			{
				return;
			}
			for (int i = 0; i < template.Templates.Count; i++)
			{
				PrefabTemplate prefabTemplate = template.Templates[i];
				if (!Templates.ContainsKey(prefabTemplate.State))
				{
					AddState(prefabTemplate.State);
				}
				Templates[prefabTemplate.State].Add($"{template.UID}:{i}", prefabTemplate);
			}
			foreach (KeyValuePair<Type, object[]> customAction in template.GetCustomActions())
			{
				RegisterCustomActions(customAction.Key, (object[])customAction.Value[1], (int)customAction.Value[0]);
			}
		}

		public void ResetTemplates(bool includePersistent = false)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in LoadedTemplates)
			{
				if ((Object)(object)loadedTemplate.Value == (Object)null || !loadedTemplate.Value.Persistent || includePersistent)
				{
					list.Add(loadedTemplate.Key);
				}
			}
			foreach (string item in list)
			{
				PrefabTemplate prefabTemplate = LoadedTemplates[item];
				if ((Object)(object)prefabTemplate != (Object)null)
				{
					Object.Destroy((Object)(object)((Component)prefabTemplate).gameObject);
				}
				LoadedTemplates.Remove(item);
			}
		}

		public void InstantiateTemplate(string uid, PrefabTemplate template)
		{
			if (!LoadedTemplates.ContainsKey(uid) && !((Object)(object)template == (Object)null))
			{
				template = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)this).transform).GetComponent<PrefabTemplate>();
				LoadedTemplates.Add(uid, template);
			}
		}

		public void InstantiateStateTemplates(string state)
		{
			if (!Templates.TryGetValue(state, out var value))
			{
				return;
			}
			foreach (KeyValuePair<string, PrefabTemplate> item in value)
			{
				InstantiateTemplate(item.Key, item.Value);
			}
		}

		public PrefabTemplate GetTemplateWithTag(params string[] tags)
		{
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in LoadedTemplates)
			{
				if (loadedTemplate.Value.HasTag(tags))
				{
					return loadedTemplate.Value;
				}
			}
			return null;
		}

		public List<PrefabTemplate> GetTemplatesWithTag(params string[] tags)
		{
			List<PrefabTemplate> list = new List<PrefabTemplate>();
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in LoadedTemplates)
			{
				if (loadedTemplate.Value.HasTag(tags))
				{
					list.Add(loadedTemplate.Value);
				}
			}
			return list;
		}

		public TaggedBehaviour GetTagInTemplates(params string[] tags)
		{
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in LoadedTemplates)
			{
				if (loadedTemplate.Value.HasTag(tags))
				{
					return loadedTemplate.Value;
				}
				foreach (TaggedBehaviour item in loadedTemplate.Value.FindTagsInChildren(tags))
				{
					if ((Object)(object)item != (Object)null)
					{
						return item;
					}
				}
			}
			return null;
		}

		public List<TaggedBehaviour> GetTagsInTemplates(params string[] tags)
		{
			List<TaggedBehaviour> list = new List<TaggedBehaviour>();
			foreach (KeyValuePair<string, PrefabTemplate> loadedTemplate in LoadedTemplates)
			{
				if (loadedTemplate.Value.HasTag(tags))
				{
					list.Add(loadedTemplate.Value);
				}
				list.AddRange(loadedTemplate.Value.FindTagsInChildren(tags));
			}
			return list;
		}

		private void Update()
		{
			if (!IsDestroyed)
			{
				StateMachine.Update();
			}
		}

		private void FixedUpdate()
		{
		}

		private void LateUpdate()
		{
		}

		private void OnDestroy()
		{
			HandleDestroy();
		}

		public void HandleDestroy(bool reset = true)
		{
			if (IsDestroyed)
			{
				return;
			}
			((Behaviour)this).enabled = false;
			IsDestroyed = true;
			StateMachine.Destroy();
			ResetTemplates(includePersistent: true);
			if (Instance != null)
			{
				Instance.DestroyHandler(reset: false, destroy: false);
				if (reset)
				{
					Instance.Reset();
				}
				else
				{
					InstanceManager.Verify();
				}
			}
			Object.Destroy((Object)(object)this);
		}
	}
	public static class TemplateRegistry
	{
		public class TemplateData
		{
			public string UID;

			public GameObject Container;

			public List<CustomActionsTemplate> CustomActionsTemplates = new List<CustomActionsTemplate>();

			public List<PrefabTemplate> Templates = new List<PrefabTemplate>();

			public TemplateData(string uid)
			{
				UID = uid;
			}

			public void InstantiateContainer()
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Expected O, but got Unknown
				Reset();
				GameObject val = new GameObject(UID ?? "");
				val.transform.parent = TemplateContainer.transform;
				Container = val;
				((Object)Container).hideFlags = (HideFlags)61;
				Container.SetActive(false);
			}

			public void InstantiatePrefab(GameObject prefab)
			{
				Reset();
				GameObject val = Object.Instantiate<GameObject>(prefab, TemplateContainer.transform);
				if (Object.op_Implicit((Object)(object)val))
				{
					Container = val;
					((Object)Container).hideFlags = (HideFlags)61;
					Container.SetActive(false);
					CustomActionsTemplate[] components = Container.GetComponents<CustomActionsTemplate>();
					foreach (CustomActionsTemplate customActions in components)
					{
						AddCustomActionsTemplate(customActions);
					}
					PrefabTemplate[] componentsInChildren = Container.GetComponentsInChildren<PrefabTemplate>();
					foreach (PrefabTemplate prefab2 in componentsInChildren)
					{
						AddTemplate(prefab2);
					}
				}
			}

			public T InstantiateCustomActionsTemplate<T>() where T : CustomActionsTemplate
			{
				if (!Object.op_Implicit((Object)(object)Container))
				{
					Debug.LogWarning((object)"Could not add CustomActionsTemplate. : Container Missing...!");
					return null;
				}
				return Container.AddComponent<T>();
			}

			public void InstantiateTemplate(GameObject prefab)
			{
				if (!Object.op_Implicit((Object)(object)Container))
				{
					Debug.LogWarning((object)"Could not instatiate Template. : Container Missing...!");
					return;
				}
				GameObject val = Object.Instantiate<GameObject>(prefab, Container.transform);
				if (!Object.op_Implicit((Object)(object)val))
				{
					Debug.LogWarning((object)"Could not instatiate Template. : Invalid Prefab...!");
					return;
				}
				PrefabTemplate component = val.GetComponent<PrefabTemplate>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					Debug.LogWarning((object)"Template does not have PrefabTemplate component.");
				}
				else
				{
					AddTemplate(component);
				}
			}

			public void AddCustomActionsTemplate(CustomActionsTemplate customActions)
			{
				CustomActionsTemplates.Add(customActions);
			}

			public void AddTemplate(PrefabTemplate prefab, bool reParent = false)
			{
				if (Object.op_Implicit((Object)(object)prefab))
				{
					if (reParent)
					{
						((Component)prefab).transform.parent = Container.transform;
					}
					Templates.Add(prefab);
				}
			}

			public Dictionary<Type, object[]> GetCustomActions()
			{
				Dictionary<Type, object[]> dictionary = new Dictionary<Type, object[]>();
				foreach (CustomActionsTemplate customActionsTemplate in CustomActionsTemplates)
				{
					Type type = customActionsTemplate.RegisterCustomActionsBaseType();
					if (type != null && !dictionary.ContainsKey(type))
					{
						dictionary.Add(type, new object[2]
						{
							customActionsTemplate.Priority,
							customActionsTemplate.PrepareTemplateData()
						});
					}
				}
				return dictionary;
			}

			public void Reset()
			{
				Object.DestroyImmediate((Object)(object)Container);
				CustomActionsTemplates.Clear();
				Templates.Clear();
			}
		}

		private static Dictionary<string, TemplateData> TemplateDatas = new Dictionary<string, TemplateData>();

		private static readonly List<string> ReservedNames = new List<string> { "none" };

		private static GameObject _templateContainer;

		public static string Default { get; private set; } = string.Empty;


		public static GameObject TemplateContainer
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)_templateContainer == (Object)null)
				{
					_templateContainer = new GameObject("UCustomPrefabsAPI_Templates");
					Object.DontDestroyOnLoad((Object)(object)_templateContainer);
					((Object)_templateContainer).hideFlags = (HideFlags)61;
					_templateContainer.SetActive(false);
				}
				return _templateContainer;
			}
		}

		public static void SetDefault(string uid)
		{
			if (TemplateDatas.ContainsKey(uid))
			{
				Default = uid;
			}
			else
			{
				Debug.LogWarning((object)("Tempate uid : \"" + uid + "\" is not registered."));
			}
		}

		public static bool TryGetTemplate(string uid, out TemplateData template)
		{
			bool flag = TemplateDatas.TryGetValue(uid, out template);
			if (!flag)
			{
				flag = TemplateDatas.TryGetValue(Default, out template);
				Debug.LogWarning((object)("Default Template will be used instead of Template uid : \"" + uid + "\""));
			}
			return flag;
		}

		public static void Register(string uid, GameObject prefab)
		{
			if (ReservedNames.Contains(uid.ToLower()))
			{
				Debug.LogWarning((object)("Template uid : \"" + uid + "\" is reserved."));
				return;
			}
			if (TemplateDatas.ContainsKey(uid))
			{
				Debug.LogWarning((object)("Template uid : \"" + uid + "\" already registered."));
				return;
			}
			if (!Object.op_Implicit((Object)(object)prefab))
			{
				Debug.LogWarning((object)("Template uid : \"" + uid + "\" prefab is invalid."));
				return;
			}
			TemplateData templateData = new TemplateData(uid);
			templateData.InstantiatePrefab(prefab);
			TemplateDatas.Add(uid, templateData);
		}

		public static void RegisterEmpty(string uid)
		{
			if (TemplateDatas.ContainsKey(uid))
			{
				Debug.LogWarning((object)("Template uid : \"" + uid + "\" already registered."));
				return;
			}
			TemplateData templateData = new TemplateData(uid);
			templateData.InstantiateContainer();
			TemplateDatas.Add(uid, templateData);
		}

		public static List<string> GetTemplatesWithCustomActions<T>() where T : CustomActionsBase
		{
			return GetTemplatesWithCustomActions(typeof(T));
		}

		public static List<string> GetTemplatesWithCustomActions(string customAction_uid)
		{
			if (!CustomActionsRegistry.TryGetActions(customAction_uid, out var actionsType))
			{
				return new List<string>();
			}
			return GetTemplatesWithCustomActions(actionsType);
		}

		private static List<string> GetTemplatesWithCustomActions(Type customAction_type)
		{
			List<string> list = new List<string>();
			foreach (KeyValuePair<string, TemplateData> templateData in TemplateDatas)
			{
				foreach (CustomActionsTemplate customActionsTemplate in templateData.Value.CustomActionsTemplates)
				{
					Type type = customActionsTemplate.RegisterCustomActionsBaseType();
					if (!(type == null) && type == customAction_type)
					{
						list.Add(templateData.Key);
					}
				}
			}
			return list;
		}
	}
	public abstract class CustomActionsTemplate : MonoBehaviour
	{
		public int Priority;

		public abstract Type RegisterCustomActionsBaseType();

		public virtual object[] PrepareTemplateData()
		{
			return null;
		}
	}
	public class PrefabTemplate : TaggedBehaviour
	{
		[Tooltip("Determines if this template get's removed on state change.")]
		public bool Persistent;

		[Tooltip("State this template is instantiated.")]
		public string State = "default";
	}
}
namespace UCustomPrefabsAPI.Extras.Utility
{
	public static class SearchUtils
	{
		public static Transform RecursivelyFindChild(Transform parent, string name)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			foreach (Transform item in parent)
			{
				Transform val = item;
				if (((Object)val).name == name)
				{
					return val;
				}
				Transform val2 = RecursivelyFindChild(val, name);
				if (Object.op_Implicit((Object)(object)val2))
				{
					return val2;
				}
			}
			return null;
		}

		public static Transform IterativelyFindChild(Transform parent, string name)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			Queue<Transform> queue = new Queue<Transform>();
			queue.Enqueue(parent);
			while (queue.Count != 0)
			{
				foreach (Transform item in parent)
				{
					Transform val = item;
					if (((Object)val).name == name)
					{
						return val;
					}
					queue.Enqueue(val);
				}
			}
			return null;
		}

		public static void RecursivelyCollectChildNames(Transform target, ref Dictionary<string, Transform> looseNameRefs)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (looseNameRefs == null)
			{
				looseNameRefs = new Dictionary<string, Transform>();
			}
			foreach (Transform item in target)
			{
				Transform val = item;
				if (!looseNameRefs.ContainsKey(((Object)val).name))
				{
					looseNameRefs.Add(((Object)val).name, val);
				}
				if (val.childCount > 0)
				{
					RecursivelyCollectChildNames(val, ref looseNameRefs);
				}
			}
		}

		public static void IterativelyCollectChildNames(Transform target, ref Dictionary<string, Transform> looseNameRefs)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			if (looseNameRefs == null)
			{
				looseNameRefs = new Dictionary<string, Transform>();
			}
			Queue<Transform> queue = new Queue<Transform>();
			queue.Enqueue(target);
			while (queue.Count != 0)
			{
				foreach (Transform item in queue.Dequeue())
				{
					Transform val = item;
					if (!looseNameRefs.ContainsKey(((Object)val).name))
					{
						looseNameRefs.Add(((Object)val).name, val);
					}
					queue.Enqueue(val);
				}
			}
		}

		public static void FixPaths(ref string[] paths, string replace, string with)
		{
			for (int i = 0; i < paths.Length; i++)
			{
				paths[i] = paths[i].Replace(replace, with);
			}
		}

		public static string FindPath(Transform root, Transform target)
		{
			string text = (Object.op_Implicit((Object)(object)target) ? ((Object)target).name : string.Empty);
			while ((Object)(object)target != (Object)null && (Object)(object)target.parent != (Object)(object)root)
			{
				target = target.parent;
				text = ((Object)target).name + "/" + text;
			}
			return text;
		}

		public static string RelativeFindPath(Transform origin, Transform target)
		{
			HashSet<Transform> hashSet = MapParentHierarchy(target);
			string text = string.Empty;
			if (hashSet.Contains(origin))
			{
				text = FindPath(origin, target);
			}
			else
			{
				foreach (Transform item in MapParentHierarchy(origin))
				{
					text += "../";
					if (hashSet.Contains(item))
					{
						text += FindPath(item, target);
						break;
					}
				}
			}
			return text;
		}

		public static Transform RelativeFind(Transform origin, string relativePath)
		{
			Queue<string> queue = new Queue<string>(relativePath.Split(new char[1] { '/' }));
			Transform val = origin;
			try
			{
				while ((Object)(object)val != (Object)null && queue.Count > 0)
				{
					string text = queue.Dequeue();
					switch (text)
					{
					case "..":
						val = val.parent;
						break;
					case "*":
						val = IterativelyFindChild(origin, queue.Dequeue());
						break;
					case "**":
						val = FindParent(val, queue.Dequeue());
						break;
					case "|":
					{
						string assetbundleName = queue.Dequeue();
						string name = queue.Dequeue();
						Transform val3 = IterativelyFindChild(val, assetbundleName);
						if (!Object.op_Implicit((Object)(object)val3))
						{
							val3 = IterativelyFindChild(val, name);
						}
						val = val3;
						break;
					}
					case "||":
					{
						string assetbundleName = queue.Dequeue();
						string name = queue.Dequeue();
						Transform val3 = FindParent(val, assetbundleName);
						if (!Object.op_Implicit((Object)(object)val3))
						{
							val3 = FindParent(val, name);
						}
						val = val3;
						break;
					}
					case "@":
					{
						string assetbundleName = queue.Dequeue();
						GameObject val2 = AssetBundleRegistry.LoadPrefab(assetbundleName, string.Join("/", queue));
						if (Object.op_Implicit((Object)(object)val2))
						{
							val = val2.transform;
						}
						break;
					}
					default:
						val = val.Find(text);
						break;
					}
				}
			}
			catch (Exception)
			{
				Debug.LogError((object)"Invalid Relative Path.");
				val = null;
			}
			return val;
		}

		public static Transform FindParent(Transform origin, string name)
		{
			bool flag = false;
			Transform val = origin;
			while (!flag && (Object)(object)val != (Object)null)
			{
				val = val.parent;
				if (((Object)val).name == name)
				{
					flag = true;
				}
			}
			if (!flag)
			{
				return null;
			}
			return val;
		}

		public static HashSet<Transform> MapParentHierarchy(Transform root)
		{
			HashSet<Transform> hashSet = new HashSet<Transform>();
			while ((Object)(object)root.parent != (Object)null)
			{
				hashSet.Add(root.parent);
				root = root.parent;
			}
			return hashSet;
		}
	}
	public class TaggedBehaviour : MonoBehaviour
	{
		[Tooltip("WIP Tags to help organize things in UCustomPrefabs.")]
		public string[] Tags;

		private HashSet<string> _tagset;

		public HashSet<string> TagSet
		{
			get
			{
				if (_tagset == null)
				{
					_tagset = new HashSet<string>();
					InitTags();
				}
				return _tagset;
			}
		}

		private void InitTags()
		{
			string[] tags = Tags;
			foreach (string item in tags)
			{
				_tagset.Add(item);
			}
		}

		public virtual void AddTag(params string[] tags)
		{
			foreach (string item in tags)
			{
				TagSet.Add(item);
			}
		}

		public virtual void RemoveTag(params string[] tags)
		{
			foreach (string item in tags)
			{
				TagSet.Remove(item);
			}
		}

		public virtual bool HasTag(params string[] tags)
		{
			foreach (string item in tags)
			{
				if (!TagSet.Contains(item))
				{
					return false;
				}
			}
			return tags.Length != 0;
		}

		public virtual void ClearTags()
		{
			TagSet.Clear();
		}

		public virtual TaggedBehaviour FindTagInChildren(params string[] tags)
		{
			TaggedBehaviour[] componentsInChildren = ((Component)this).GetComponentsInChildren<TaggedBehaviour>(true);
			foreach (TaggedBehaviour taggedBehaviour in componentsInChildren)
			{
				if (taggedBehaviour.HasTag(tags))
				{
					return taggedBehaviour;
				}
			}
			return null;
		}

		public virtual List<TaggedBehaviour> FindTagsInChildren(params string[] tags)
		{
			List<TaggedBehaviour> list = new List<TaggedBehaviour>();
			TaggedBehaviour[] componentsInChildren = ((Component)this).GetComponentsInChildren<TaggedBehaviour>(true);
			foreach (TaggedBehaviour taggedBehaviour in componentsInChildren)
			{
				if (taggedBehaviour.HasTag(tags))
				{
					list.Add(taggedBehaviour);
				}
			}
			return list;
		}
	}
	public class TaggedData : TaggedBehaviour
	{
		[Tooltip("WIP Tag Data to help serialize things in UCustomPrefabs.")]
		public string[] Data;

		private Dictionary<string, string> _tagdata;

		public Dictionary<string, string> TagData
		{
			get
			{
				if (_tagdata == null)
				{
					_tagdata = new Dictionary<string, string>();
					InitTagData();
				}
				return _tagdata;
			}
		}

		private void InitTagData()
		{
			for (int i = 0; i < Data.Length && i < Tags.Length; i++)
			{
				try
				{
					_tagdata.Add(Tags[i], Data[i]);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			}
		}

		public override void AddTag(params string[] tags)
		{
			for (int i = 0; i + 1 < tags.Length; i += 2)
			{
				base.TagSet.Add(tags[i]);
				try
				{
					TagData.Add(tags[i], tags[i + 1]);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			}
		}

		public override void RemoveTag(params string[] tags)
		{
			foreach (string text in tags)
			{
				base.TagSet.Remove(text);
				try
				{
					TagData.Remove(text);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			}
		}

		public bool TryGetTagData(string tag, out string data)
		{
			return TagData.TryGetValue(tag, out data);
		}
	}
}
namespace UCustomPrefabsAPI.Extras.Utility.Serialization
{
	public abstract class MonobehaviourSerialized : MonoBehaviour, ISerializationCallbackReceiver
	{
		public string Data = string.Empty;

		public void OnAfterDeserialize()
		{
			if (!string.IsNullOrWhiteSpace(Data))
			{
				string data = Data;
				JsonUtility.FromJsonOverwrite(Data, (object)this);
				Data = data;
			}
		}

		public void OnBeforeSerialize()
		{
			Data = string.Empty;
			Data = JsonUtility.ToJson((object)this);
		}
	}
}
namespace UCustomPrefabsAPI.Extras.Tokens
{
	public static class TokenRegistry
	{
		private static Dictionary<string, string> _tokens = new Dictionary<string, string>();

		private static Dictionary<string, HashSet<Action<string>>> _listeners = new Dictionary<string, HashSet<Action<string>>>();

		public static void SetToken(string token, string data)
		{
			if (!_tokens.ContainsKey(token))
			{
				_tokens.Add(token, data);
			}
			else
			{
				_tokens[token] = data;
			}
		}

		public static string GetToken(string token)
		{
			if (!_tokens.TryGetValue(token, out var value))
			{
				return string.Empty;
			}
			return value;
		}

		public static void InvokeListeners(string token)
		{
			if (!_listeners.TryGetValue(token, out var value))
			{
				return;
			}
			foreach (Action<string> item in value)
			{
				try
				{
					item?.Invoke(token);
				}
				catch (Exception ex)
				{
					Debug.LogError((object)ex);
				}
			}
		}

		public static void Listen(string token, Action<string> action)
		{
			if (!_listeners.TryGetValue(token, out var value))
			{
				value = new HashSet<Action<string>>();
				_listeners.Add(token, value);
			}
			value.Add(action);
		}

		public static void StopListening(string token, Action<string> action)
		{
			if (_listeners.TryGetValue(token, out var value))
			{
				value.Remove(action);
			}
		}

		public static void RemoveListeners(string token)
		{
			if (_listeners.TryGetValue(token, out var value))
			{
				value.Clear();
			}
		}
	}
}
namespace UCustomPrefabsAPI.Extras.Profiles
{
	public class Profile
	{
		private Dictionary<string, ProfileData> _data = new Dictionary<string, ProfileData>();

		private List<ProfileData> _list = new List<ProfileData>();

		private bool locked;

		private WeakReference<ProfileManager> _manager;

		private const char START_TAG = '[';

		private const char END_TAG = ']';

		public int Count => _list.Count;

		public ProfileManager Manager
		{
			get
			{
				if (_manager != null && _manager.TryGetTarget(out var target))
				{
					return target;
				}
				return null;
			}
		}

		public void SetManager(ProfileManager manager)
		{
			if (manager != null)
			{
				_manager = new WeakReference<ProfileManager>(manager);
			}
		}

		public Profile(ProfileManager manager)
		{
			SetManager(manager);
		}

		public Profile Clone()
		{
			Profile profile = new Profile(Manager);
			foreach (KeyValuePair<string, ProfileData> datum in _data)
			{
				ProfileData value = datum.Value;
				profile.SetData(datum.Key, value.Data, value.GetType());
			}
			foreach (KeyValuePair<string, ProfileData> datum2 in _data)
			{
				ProfileData value2 = datum2.Value;
				int index = _list.IndexOf(value2);
				profile.SetDataIndex(datum2.Key, index);
			}
			return profile;
		}

		public void SetData(string key, object value, Type type)
		{
			if (Manager == null)
			{
				return;
			}
			if (!_data.TryGetValue(key, out var value2) && !locked)
			{
				if (!Manager.TryInstantiateDataType(type, out value2))
				{
					_data.Add(key, value2);
				}
				_list.Add(value2);
				value2.Data = value;
			}
			else
			{
				value2.Data = value;
			}
		}

		public void SetData<T>(string key, T value)
		{
			SetData(key, value, typeof(T));
		}

		public T GetData<T>(string key)
		{
			TryGetData<T>(key, out var value);
			return value;
		}

		public bool TryGetData<T>(string key, out T value)
		{
			ProfileData value2;
			bool num = _data.TryGetValue(key, out value2);
			if (num)
			{
				value = (T)value2.Data;
				return num;
			}
			value = default(T);
			return num;
		}

		public bool HasData(string key)
		{
			return _data.ContainsKey(key);
		}

		public void RemoveData(string key)
		{
			if (!locked && _data.TryGetValue(key, out var value))
			{
				_data.Remove(key);
				_list.Remove(value);
			}
		}

		public void PurgeData()
		{
			if (!locked)
			{
				_data.Clear();
				_list.Clear();
			}
		}

		public void SetDataIndex(string key, int index)
		{
			if (!locked && _data.TryGetValue(key, out var value) && _list.IndexOf(value) != index)
			{
				_list.Remove(value);
				_list.Insert(index, value);
			}
		}

		public int GetDataIndex(string key)
		{
			if (!_data.TryGetValue(key, out var value))
			{
				return -1;
			}
			return _list.IndexOf(value);
		}

		public void LockEdits()
		{
			locked = true;
		}

		public string Serialize(bool useChecksum = true)
		{
			List<string> list = new List<string>();
			for (int i = 0; i < Count; i++)
			{
				list.Add(string.Empty);
			}
			foreach (KeyValuePair<string, ProfileData> datum in _data)
			{
				ProfileData value = datum.Value;
				string text = value.Serailize();
				if (value.Size == -1)
				{
					text = $"{'['}{text}{']'}";
				}
				list[GetDataIndex(datum.Key)] = text;
			}
			string text2 = string.Join(string.Empty, list);
			if (useChecksum)
			{
				text2 = GenerateChecksum(text2) + text2;
			}
			return text2;
		}

		public void Deserialize(string input, bool hasChecksum = true, int offset = 0)
		{
			if (hasChecksum && !ValidateChecksum(input))
			{
				Debug.LogWarning((object)"Profile data does not match checksum--");
				Debug.LogWarning((object)"data may be incorrect... Ignoring");
				return;
			}
			int num = (hasChecksum ? 1 : 0);
			for (int i = offset; i < _list.Count; i++)
			{
				ProfileData profileData = _list[i];
				int num2 = profileData.Size;
				bool flag = num2 == -1;
				if (flag)
				{
					num2 = FindDataSize(input, num);
				}
				if (num2 > 0)
				{
					string data = ((!flag) ? input.Substring(num, num2) : input.Substring(num + 1, num2 - 1));
					profileData.Deserialize(data);
					num += num2;
				}
			}
		}

		private bool ValidateChecksum(string input)
		{
			char num = input[0];
			char c = GenerateChecksum(input, 1);
			return num == c;
		}

		private char GenerateChecksum(string input, int offset = 0)
		{
			int i = offset;
			char c = '#';
			for (; i < input.Length; i++)
			{
				char c2 = input[i];
				c ^= c2;
				bool num = c % 2 == 0;
				c = (char)(c % 26 + 65);
				c = (num ? char.ToUpper(c) : char.ToLower(c));
			}
			return c;
		}

		private int FindDataSize(string input, int pointer)
		{
			pointer = input.IndexOf('[', pointer);
			if (pointer < 0)
			{
				return -1;
			}
			int num = 0;
			int num2 = 0;
			while (pointer < input.Length)
			{
				switch (input[pointer])
				{
				case '[':
					num2++;
					break;
				case ']':
					num2--;
					break;
				}
				if (num2 == 0)
				{
					break;
				}
				num++;
				pointer++;
			}
			return num;
		}
	}
	public abstract class ProfileData
	{
		public object Data { get; set; }

		public Type Type { get; set; } = typeof(string);


		public int Size { get; set; } = -1;


		public virtual bool TryGet<T>(out T data)
		{
			data = default(T);
			int num;
			if (Data != null)
			{
				num = (Type.IsInstanceOfType(typeof(T)) ? 1 : 0);
				if (num != 0)
				{
					data = (T)Data;
					return (byte)num != 0;
				}
			}
			else
			{
				num = 0;
			}
			Debug.Log((object)"Data is invalid.");
			return (byte)num != 0;
		}

		public virtual string Serailize()
		{
			if (Data == null)
			{
				return null;
			}
			string text = Data.ToString();
			if (Size != -1)
			{
				try
				{
					text = text.Substring(0, Size);
				}
				catch (Exception)
				{
					Debug.Log((object)"Data is too small.");
				}
			}
			return text;
		}

		public virtual void Deserialize(string data)
		{
			if (string.IsNullOrEmpty(data))
			{
				return;
			}
			if (Size != -1)
			{
				try
				{
					data = data.Substring(0, Size);
				}
				catch (Exception)
				{
					Debug.Log((object)"Data is too small.");
				}
			}
			Data = data;
		}
	}
	public class ProfileManager
	{
		private Dictionary<string, Profile> Profiles = new Dictionary<string, Profile>();

		private Profile Template;

		private Dictionary<Type, Type> DataTypes = new Dictionary<Type, Type>
		{
			{
				typeof(string),
				typeof(ProfileData)
			},
			{
				typeof(float),
				typeof(ProfileData_Float)
			},
			{
				typeof(int),
				typeof(ProfileData_Integer)
			},
			{
				typeof(bool),
				typeof(ProfileData_Boolean)
			},
			{
				typeof(char),
				typeof(ProfileData_Char)
			}
		};

		public Profile InstantiateProfile()
		{
			return new Profile(this);
		}

		public Profile CreateProfile(string name)
		{
			if (Template == null)
			{
				return null;
			}
			if (TryGetProfile(name, out var config))
			{
				return config;
			}
			config = Template.Clone();
			config.LockEdits();
			Profiles.Add(name, config);
			return config;
		}

		public bool TryGetProfile(string name, out Profile config)
		{
			return Profiles.TryGetValue(name, out config);
		}

		public void RegisterTemplate(Profile profile)
		{
			ClearTemplate();
			Template = profile;
		}

		public void ClearProfiles()
		{
			Profiles.Clear();
		}

		public void ClearTemplate()
		{
			Template = null;
		}

		public void RegisterDataType<T>(Type type) where T : ProfileData
		{
			try
			{
				DataTypes.Add(type, typeof(T));
			}
			catch (ArgumentException)
			{
				Console.WriteLine("Data Type Already Registered.");
			}
		}

		public bool TryInstantiateDataType(Type type, out ProfileData data)
		{
			data = null;
			if (DataTypes.TryGetValue(type, out var value))
			{
				data = (ProfileData)Activator.CreateInstance(value);
			}
			return data != null;
		}
	}
	internal static class ProfileRegistry
	{
		private static Dictionary<string, ProfileManager> ProfileManagers = new Dictionary<string, ProfileManager>();

		public static ProfileManager CreateProfileManager(string uid)
		{
			if (ProfileManagers.TryGetValue(uid, out var value))
			{
				return value;
			}
			value = new ProfileManager();
			ProfileManagers.Add(uid, value);
			return value;
		}

		public static Profile CreateProfile(string uid, string name)
		{
			ProfileManagers.TryGetValue(uid, out var value);
			return value?.CreateProfile(name);
		}

		public static void RegisterProfileTemplate(string uid, Profile template)
		{
			ProfileManagers.TryGetValue(uid, out var value);
			value?.RegisterTemplate(template);
		}

		public static bool TryGetProfile(string uid, string name, out Profile profile)
		{
			profile = null;
			if (!ProfileManagers.TryGetValue(uid, out var value))
			{
				return false;
			}
			return value.TryGetProfile(name, out profile);
		}
	}
	public class ProfileData_Float : ProfileData
	{
		public ProfileData_Float()
		{
			base.Type = typeof(float);
		}

		public override void Deserialize(string data)
		{
			if (float.TryParse(data, out var result))
			{
				base.Data = result;
			}
		}
	}
	public class ProfileData_Integer : ProfileData
	{
		public ProfileData_Integer()
		{
			base.Type = typeof(int);
		}

		public override void Deserialize(string data)
		{
			if (int.TryParse(data, out var result))
			{
				base.Data = result;
			}
		}
	}
	public class ProfileData_Boolean : ProfileData
	{
		public ProfileData_Boolean()
		{
			base.Type = typeof(bool);
			base.Size = 1;
		}

		public override string Serailize()
		{
			if (!TryGet<bool>(out var data))
			{
				return "0";
			}
			if (!data)
			{
				return "0";
			}
			return "1";
		}

		public override void Deserialize(string data)
		{
			if (string.IsNullOrEmpty(data))
			{
				return;
			}
			bool result;
			if (data.Length == 1)
			{
				switch (data.ToUpper())
				{
				case "T":
					base.Data = true;
					break;
				case "F":
					base.Data = false;
					break;
				case "1":
					base.Data = true;
					break;
				case "0":
					base.Data = false;
					break;
				}
			}
			else if (bool.TryParse(data, out result))
			{
				base.Data = result;
			}
		}
	}
	public class ProfileData_Char : ProfileData
	{
		public ProfileData_Char()
		{
			base.Type = typeof(char);
			base.Size = 1;
		}

		public override void Deserialize(string data)
		{
			if (!string.IsNullOrEmpty(data) && data.Length > 0)
			{
				base.Data = data[0];
			}
		}
	}
}
namespace UCustomPrefabsAPI.Extras.CustomActions
{
	public static class CustomActionsRegistry
	{
		private static Dictionary<string, Type> RegisteredCustomActions = new Dictionary<string, Type>();

		public static bool TryGetActions(string uid, out Type actionsType)
		{
			return RegisteredCustomActions.TryGetValue(uid, out actionsType);
		}

		public static void Register<T>(string uid) where T : CustomActionsBase
		{
			if (RegisteredCustomActions.ContainsKey(uid))
			{
				Debug.LogWarning((object)("CustomActions uid : \"" + uid + "\" already registered."));
			}
			else
			{
				RegisteredCustomActions.Add(uid, typeof(T));
			}
		}
	}
	public class LooseReferenceAction : CustomActionsTemplate
	{
		[SerializeField]
		public string CustomActionName;

		[SerializeField]
		public string Data;

		public override Type RegisterCustomActionsBaseType()
		{
			CustomActionsRegistry.TryGetActions(CustomActionName, out var actionsType);
			return actionsType;
		}

		public override object[] PrepareTemplateData()
		{
			return new object[1] { Data };
		}
	}
}
namespace UCustomPrefabsAPI.Extras.AssetBundles
{
	public class AssetBundleData
	{
		public string name;

		public string path;

		public bool embedded;

		public Assembly assembly;

		public AssetBundle assetbundle;

		public AssetBundleData(Type origin, string path, string name = null, bool embedded = false)
		{
			assembly = origin.Assembly;
			this.path = path;
			this.embedded = embedded;
			if (string.IsNullOrWhiteSpace(name))
			{
				name = Path.GetFileName(path);
			}
			this.name = name;
		}

		public bool LoadAssetBundle()
		{
			if (string.IsNullOrWhiteSpace(path))
			{
				return false;
			}
			if (embedded)
			{
				return LoadEmbedded();
			}
			return Load();
		}

		private bool Load()
		{
			assetbundle = null;
			try
			{
				string text = Path.Combine(Path.GetDirectoryName(assembly.Location), path);
				assetbundle = AssetBundle.LoadFromFile(text);
			}
			catch (Exception ex)
			{
				Debug.Log((object)"Unable to load assetbundle. Make sure your pathing is correct.");
				Debug.Log((object)"Make sure to use LoadEmbeddedAssetBundle if using an embedded resource");
				Debug.LogError((object)ex);
			}
			if (!Object.op_Implicit((Object)(object)assetbundle))
			{
				return false;
			}
			embedded = false;
			return true;
		}

		private bool LoadEmbedded()
		{
			assetbundle = null;
			try
			{
				string text = path.Replace('\\', '.');
				text = text.Replace('/', '.');
				text = assembly.FullName.Split(new char[1] { ',' })[0] + "." + text;
				using Stream stream = assembly.GetManifestResourceStream(text);
				assetbundle = AssetBundle.LoadFromStream(stream);
			}
			catch (Exception ex)
			{
				Debug.Log((object)"Unable to load assetbundle. Make sure your pathing is correct.");
				Debug.Log((object)"Embedded Resources use \".\" instead of the usual \"\\\".");
				Debug.LogError((object)ex);
			}
			if (!Object.op_Implicit((Object)(object)assetbundle))
			{
				return false;
			}
			return true;
		}

		public GameObject LoadPrefab(string name)
		{
			AssetBundle obj = assetbundle;
			if (obj == null)
			{
				return null;
			}
			return obj.LoadAsset<GameObject>(name);
		}

		public T LoadAsset<T>(string name) where T : Object
		{
			AssetBundle obj = assetbundle;
			if (obj == null)
			{
				return default(T);
			}
			return obj.LoadAsset<T>(name);
		}

		public void Unload(bool unloadAllLoadedObjects)
		{
			AssetBundle obj = assetbundle;
			if (obj != null)
			{
				obj.Unload(unloadAllLoadedObjects);
			}
		}
	}
	public static class AssetBundleRegistry
	{
		private static Dictionary<string, AssetBundleData> AssetBundles = new Dictionary<string, AssetBundleData>();

		public static bool Register<T>(string path, string name = null)
		{
			AssetBundleData assetBundleData = new AssetBundleData(typeof(T), path, name);
			if (HasAssetBundle(assetBundleData.name) || !assetBundleData.LoadAssetBundle())
			{
				return false;
			}
			AssetBundles.Add(assetBundleData.name, assetBundleData);
			return true;
		}

		public static bool Register<T>(string path, out string name)
		{
			name = null;
			AssetBundleData assetBundleData = new AssetBundleData(typeof(T), path);
			if (HasAssetBundle(assetBundleData.name) || !assetBundleData.LoadAssetBundle())
			{
				return false;
			}
			AssetBundles.Add(assetBundleData.name, assetBundleData);
			name = assetBundleData.name;
			return true;
		}

		public static void RegisterEmbedded<T>(string path, string name = null)
		{
			AssetBundleData assetBundleData = new AssetBundleData(typeof(T), path, name, embedded: true);
			if (!HasAssetBundle(assetBundleData.name) && assetBundleData.LoadAssetBundle())
			{
				AssetBundles.Add(assetBundleData.name, assetBundleData);
			}
		}

		public static void Remove(string assetbundleName, bool unloadAllLoadedObjects)
		{
			if (AssetBundles.TryGetValue(assetbundleName, out var value))
			{
				value.Unload(unloadAllLoadedObjects);
				AssetBundles.Remove(assetbundleName);
			}
		}

		public static bool HasAssetBundle(string name)
		{
			return AssetBundles.ContainsKey(name);
		}

		public static GameObject LoadPrefab(string assetbundleName, string name)
		{
			if (!AssetBundles.TryGetValue(assetbundleName, out var value))
			{
				return null;
			}
			return value.LoadPrefab(name);
		}

		public static T LoadAsset<T>(string assetbundleName, string name) where T : Object
		{
			if (!AssetBundles.TryGetValue(assetbundleName, out var value))
			{
				return default(T);
			}
			return value.LoadAsset<T>(name);
		}
	}
}
namespace UCustomPrefabsAPI.Extras.Animation
{
	[Serializable]
	public class BoneMapPair
	{
		public string origin = string.Empty;

		public string target = string.Empty;
	}
	[Serializable]
	public class BoneMap
	{
		public bool UsePaths;

		private Dictionary<string, BoneMapPair> _dict = new Dictionary<string, BoneMapPair>();

		public List<BoneMapPair> bonePairs = new List<BoneMapPair>();

		public void AddDefaultHumanBoneNames()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			ClearPairs();
			HumanBodyBones[] humanBodyBonesAry = RigUtilities.HumanBodyBonesAry;
			for (int i = 0; i < humanBodyBonesAry.Length; i++)
			{
				HumanBodyBones val = humanBodyBonesAry[i];
				AddPair(((object)(HumanBodyBones)(ref val)).ToString(), string.Empty);
			}
		}

		public void AddHumanBones(Animator animator)
		{
			//IL_0026: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)animator))
			{
				Debug.LogWarning((object)"Animator not found.");
				return;
			}
			ClearPairs();
			HumanBodyBones[] humanBodyBonesAry = RigUtilities.HumanBodyBonesAry;
			foreach (HumanBodyBones val in humanBodyBonesAry)
			{
				try
				{
					Transform boneTransform = animator.GetBoneTransform(val);
					if (Object.op_Implicit((Object)(object)boneTransform))
					{
						if (UsePaths)
						{
							AddPair(Enum.GetName(typeof(HumanBodyBones), val), SearchUtils.FindPath(((Component)animator).transform, boneTransform));
						}
						else
						{
							AddPair(Enum.GetName(typeof(HumanBodyBones), val), ((Object)boneTransform).name);
						}
					}
				}
				catch (Exception)
				{
				}
			}
		}

		public void AddRecursiveBones(Transform target)
		{
			ClearPairs();
			Dictionary<string, Transform> looseNameRefs = new Dictionary<string, Transform>();
			SearchUtils.RecursivelyCollectChildNames(target, ref looseNameRefs);
			foreach (KeyValuePair<string, Transform> item in looseNameRefs)
			{
				if (UsePaths)
				{
					AddPair(item.Key, SearchUtils.FindPath(target, item.Value));
				}
				else
				{
					AddPair(item.Key, item.Key);
				}
			}
		}

		public List<string> MatchBoneMaps(BoneMap target)
		{
			ValidateDict();
			List<string> list = new List<string>();
			if (target == null)
			{
				Debug.Log((object)"Cannot Match BoneMaps!!!");
			}
			else
			{
				foreach (BoneMapPair bonePair in bonePairs)
				{
					if (target.HasPair(bonePair.origin))
					{
						list.Add(bonePair.origin);
					}
				}
			}
			return list;
		}

		public bool HasPair(string origin)
		{
			ValidateDict();
			if (!_dict.TryGetValue(origin, out var value))
			{
				return false;
			}
			return !string.IsNullOrWhiteSpace(value.target);
		}

		public string FetchPair(string origin)
		{
			ValidateDict();
			if (!_dict.TryGetValue(origin, out var value))
			{
				return string.Empty;
			}
			return value.target;
		}

		public void AddPair(string origin, string target)
		{
			ValidateDict();
			if (!_dict.ContainsKey(origin))
			{
				BoneMapPair boneMapPair = new BoneMapPair
				{
					origin = origin,
					target = target
				};
				bonePairs.Add(boneMapPair);
				_dict.Add(origin, boneMapPair);
			}
		}

		public void RemovePair(string origin)
		{
			ValidateDict();
			if (_dict.TryGetValue(origin, out var value))
			{
				bonePairs.Remove(value);
				_dict.Remove(origin);
			}
		}

		public void ClearEmptyPairs()
		{
			ValidateDict();
			HashSet<string> hashSet = new HashSet<string>(_dict.Keys);
			foreach (BoneMapPair bonePair in bonePairs)
			{
				if (!string.IsNullOrEmpty(bonePair.target))
				{
					hashSet.Remove(bonePair.origin);
				}
			}
			foreach (string item in hashSet)
			{
				_dict.Remove(item);
			}
		}

		public void ClearPairs()
		{
			_dict.Clear();
			bonePairs.Clear();
		}

		public void ValidateDict()
		{
			HashSet<string> hashSet = new HashSet<string>(_dict.Keys);
			foreach (BoneMapPair bonePair in bonePairs)
			{
				if (_dict.ContainsKey(bonePair.origin))
				{
					hashSet.Remove(bonePair.origin);
				}
				else
				{
					_dict.Add(bonePair.origin, bonePair);
				}
			}
			foreach (string item in hashSet)
			{
				_dict.Remove(item);
			}
		}
	}
	[Serializable]
	public class BoneRigInfo
	{
		public string version = string.Empty;

		public List<Quaternion> rotations = new List<Quaternion>();

		public bool useRotations = true;

		public List<Vector3> positions = new List<Vector3>();

		public bool usePositions;

		public List<string> originPaths = new List<string>();

		public List<string> targetPaths = new List<string>();

		public int rootIndex = -1;

		public Vector3 offset = Vector3.zero;

		public bool originUsePaths;

		public bool targetUsePaths;
	}
	public class BoneRigTracker
	{
		public Transform origin;

		public Transform target;

		public List<Transform> originBones = new List<Transform>();

		public List<Transform> targetBones = new List<Transform>();

		public List<Quaternion> rotations = new List<Quaternion>();

		public bool useRotations;

		public List<Vector3> positions = new List<Vector3>();

		public bool usePositions;

		public int rootIndex = -1;

		public Transform pivot;

		public Vector3 offset = Vector3.zero;

		public BoneRigTracker(Transform origin, Transform target)
		{
			//IL_0034: 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)
			this.origin = origin;
			this.target = target;
		}

		public void SetUpRig(BoneRigInfo info, Transform pivot = null)
		{
			if (info != null)
			{
				this.pivot = pivot;
				rotations = new List<Quaternion>(info.rotations);
				useRotations = info.useRotations;
				positions = new List<Vector3>(info.positions);
				usePositions = info.usePositions;
				rootIndex = info.rootIndex;
				RegisterBones(info);
				VerifyBones();
			}
		}

		private void RegisterBones(BoneRigInfo info)
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)origin) || !Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			int count = info.originPaths.Count;
			originBones = new List<Transform>(count);
			targetBones = new List<Transform>(count);
			Dictionary<string, Transform> looseNameRefs = null;
			Dictionary<string, Transform> looseNameRefs2 = null;
			if (!info.originUsePaths)
			{
				SearchUtils.IterativelyCollectChildNames(origin, ref looseNameRefs);
			}
			if (!info.targetUsePaths)
			{
				SearchUtils.IterativelyCollectChildNames(target, ref looseNameRefs2);
			}
			for (int i = 0; i < count; i++)
			{
				Transform value;
				if (info.originUsePaths)
				{
					value = origin.Find(info.originPaths[i]);
				}
				else
				{
					looseNameRefs.TryGetValue(info.originPaths[i], out value);
				}
				Transform value2;
				if (info.targetUsePaths)
				{
					value2 = target.Find(info.targetPaths[i]);
				}
				else
				{
					looseNameRefs2.TryGetValue(info.targetPaths[i], out value2);
				}
				originBones.Add(value);
				targetBones.Add(value2);
			}
			VerifyBones();
			if (info.version == "0.0.4")
			{
				offset = info.offset;
			}
			else if (rootIndex >= 0 && rootIndex < targetBones.Count)
			{
				Transform val = targetBones[rootIndex];
				offset = val.position - Vector3.Project(info.offset, val.up);
				offset = val.InverseTransformVector(offset - val.position);
			}
		}

		public void VerifyBones()
		{
			for (int i = 0; i < originBones.Count; i++)
			{
				if (i >= 0 && (!Object.op_Implicit((Object)(object)originBones[i]) || !Object.op_Implicit((Object)(object)targetBones[i])))
				{
					RemoveBone(i);
					i--;
				}
			}
		}

		public void RemoveBone(int index)
		{
			Debug.LogWarning((object)"Removing Bone!");
			try
			{
				originBones.RemoveAt(index);
				targetBones.RemoveAt(index);
				if (useRotations)
				{
					rotations.RemoveAt(index);
				}
				if (usePositions)
				{
					positions.RemoveAt(index);
				}
				if (index < rootIndex && rootIndex != -1)
				{
					rootIndex--;
				}
				else if (rootIndex == index || rootIndex < 0 || rootIndex == originBones.Count)
				{
					rootIndex = -1;
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex);
			}
		}

		public bool GetBonePair(int index, out Transform origin, out Transform target)
		{
			origin = originBones[index];
			target = targetBones[index];
			if ((Object)(object)origin == (Object)null || (Object)(object)target == (Object)null)
			{
				Debug.LogWarning((object)"Bone seem to be invalid, Will Verify Bone Rig.");
				VerifyBones();
				Update();
				return false;
			}
			return true;
		}

		public void Update()
		{
			for (int i = 0; i < originBones.Count; i++)
			{
				if (!GetBonePair(i, out var val, out var val2))
				{
					return;
				}
				if (useRotations)
				{
					UpdateBoneRotation(i, val, val2);
				}
				if (usePositions)
				{
					UpdateBonePosition(i, val, val2);
				}
			}
			UpdatePivotOffset();
		}

		private void UpdateBoneRotation(int index, Transform origin, Transform target)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			RigUtilities.ApplyRotationOffset(origin, target, rotations[index]);
		}

		private void UpdateBonePosition(int index, Transform origin, Transform target)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			RigUtilities.ApplyPositionOffset(origin, target, positions[index]);
		}

		public void UpdatePivotOffset()
		{
			//IL_005e: 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)
			if (rootIndex != -1)
			{
				if ((Object)(object)pivot != (Object)null)
				{
					RigUtilities.ApplyPositionOffset(originBones[rootIndex], pivot, offset);
				}
				else
				{
					RigUtilities.ApplyPositionOffset(originBones[rootIndex], targetBones[rootIndex], offset);
				}
			}
		}
	}
	[Serializable]
	public class RigBuilder : MonoBehaviour
	{
		private BoneRigInfo _rig;

		public string Data = string.Empty;

		public BoneRigInfo Rig
		{
			get
			{
				if (_rig == null)
				{
					Deserialize();
				}
				return _rig;
			}
		}

		public void Deserialize()
		{
			if (string.IsNullOrWhiteSpace(Data))
			{
				return;
			}
			_rig = new BoneRigInfo();
			try
			{
				JsonUtility.FromJsonOverwrite(Data, (object)_rig);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex);
			}
		}
	}
	[Serializable]
	public class RigBuilderTemplate : MonoBehaviour
	{
		public GameObject RigPrefab;

		public AnimationClip ReferencePose;

		public bool PoseTargetRig;

		public bool PoseTemplateRig;

		public string RootName = "Hips";

		private BoneMap _bonemap;

		public string Data = string.Empty;

		public BoneMap BoneMap
		{
			get
			{
				if (_bonemap == null)
				{
					Deserialize();
				}
				return _bonemap;
			}
		}

		public virtual bool BuildRig(Transform target, BoneMap targetBoneMap, out BoneRigInfo rig)
		{
			return RigUtilities.TryBuildRig(this, target, targetBoneMap, out rig);
		}

		public void Deserialize()
		{
			if (string.IsNullOrEmpty(Data))
			{
				return;
			}
			if (_bonemap == null)
			{
				_bonemap = new BoneMap();
			}
			try
			{
				JsonUtility.FromJsonOverwrite(Data, (object)_bonemap);
				_bonemap.ValidateDict();
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex);
			}
		}
	}
	public static class RigUtilities
	{
		public const string CurrentRigVersion = "0.0.4";

		public static HumanBodyBones[] HumanBodyBonesAry = (HumanBodyBones[])Enum.GetValues(typeof(HumanBodyBones));

		public static bool TryBuildRig(RigBuilderTemplate Template, Transform target, BoneMap targetBoneMap, out BoneRigInfo rig)
		{
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			rig = null;
			Transform val = null;
			Transform val2 = null;
			try
			{
				val = ((Component)Object.Instantiate<Transform>(target, (Transform)null)).transform;
				val2 = Object.Instantiate<GameObject>(Template.RigPrefab, (Transform)null).transform;
				if (Template.PoseTargetRig)
				{
					AnimationClip referencePose = Template.ReferencePose;
					if (referencePose != null)
					{
						referencePose.SampleAnimation(((Component)val).gameObject, 0f);
					}
				}
				if (Template.PoseTemplateRig)
				{
					AnimationClip referencePose2 = Template.ReferencePose;
					if (referencePose2 != null)
					{
						referencePose2.SampleAnimation(((Component)val2).gameObject, 0f);
					}
				}
				Dictionary<string, Transform> looseNameRefs = new Dictionary<string, Transform>();
				Dictionary<string, Transform> looseNameRefs2 = new Dictionary<string, Transform>();
				SearchUtils.RecursivelyCollectChildNames(val, ref looseNameRefs);
				SearchUtils.RecursivelyCollectChildNames(val2, ref looseNameRefs2);
				List<string> list = targetBoneMap.MatchBoneMaps(Template.BoneMap);
				List<KeyValuePair<Transform, Transform>> list2 = new List<KeyValuePair<Transform, Transform>>();
				List<string> list3 = new List<string>();
				foreach (string item in list)
				{
					Transform value = null;
					Transform value2 = null;
					string text = targetBoneMap.FetchPair(item);
					string text2 = Template.BoneMap.FetchPair(item);
					if (targetBoneMap.UsePaths)
					{
						value = val.Find(text);
					}
					else
					{
						looseNameRefs.TryGetValue(text, out value);
					}
					if (Template.BoneMap.UsePaths)
					{
						value2 = val2.Find(text2);
					}
					else
					{
						looseNameRefs2.TryGetValue(text2, out value2);
					}
					if (Object.op_Implicit((Object)(object)value2) && Object.op_Implicit((Object)(object)value))
					{
						list2.Add(new KeyValuePair<Transform, Transform>(value, value2));
						list3.Add(item);
					}
				}
				int count = list2.Count;
				rig = new BoneRigInfo();
				rig.version = "0.0.4";
				rig.originUsePaths = targetBoneMap.UsePaths;
				rig.targetUsePaths = Template.BoneMap.UsePaths;
				for (int i = 0; i < count; i++)
				{
					string text3 = list3[i];
					Transform value3 = list2[i].Value;
					Transform key = list2[i].Key;
					rig.targetPaths.Add(Template.BoneMap.FetchPair(text3));
					rig.originPaths.Add(targetBoneMap.FetchPair(text3));
					rig.rotations.Add(CalculateRotationOffset(value3, key));
					if (rig.rootIndex == -1 && text3 == Template.RootName)
					{
						rig.rootIndex = i;
						rig.offset = CalculatePositionOffset(key, value3);
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)ex);
				return false;
			}
			finally
			{
				Object.DestroyImmediate((Object)(object)((val != null) ? ((Component)val).gameObject : null));
				Object.DestroyImmediate((Object)(object)((val2 != null) ? ((Component)val2).gameObject : null));
			}
			return true;
		}

		public static float CalculateHeightRatio(Transform origin, Transform target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			return origin.position.y / target.position.y;
		}

		public static Vector3 CalculatePositionOffset(Transform origin, Transform target)
		{
			//IL_0002: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return target.InverseTransformVector(origin.position - target.position);
		}

		public static Quaternion CalculateRotationOffset(Transform origin, Transform target)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			return Quaternion.Inverse(origin.rotation) * target.rotation;
		}

		public static void ApplyPositionOffset(Transform origin, Transform target, Vector3 offset)
		{
			//IL_0002: 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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			origin.position = target.position + target.TransformVector(offset);
		}

		public static void ApplyRotationOffset(Transform origin, Transform target, Quaternion offset)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//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)
			origin.rotation = target.rotation * offset;
		}
	}
}