Decompiled source of Body Model Additions API v2.1.0

plugins/BodyModelAdditionsAPI.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using HG.Reflection;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using On.RoR2;
using On.RoR2.SurvivorMannequins;
using RoR2;
using RoR2.Skills;
using RoR2.SurvivorMannequins;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BodyModelAdditionsAPI")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+365ad4c17e3a88aae4b8878ea0ecdebe94e2c9f4")]
[assembly: AssemblyProduct("BodyModelAdditionsAPI")]
[assembly: AssemblyTitle("BodyModelAdditionsAPI")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
[module: UnverifiableCode]
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 BodyModelAdditionsAPI
{
	[Serializable]
	[BepInPlugin("com.brynzananas.bodymodeladditionsapi", "Body Model Additions API", "2.1.0")]
	[BepInDependency("com.bepis.r2api", "5.0.10")]
	public class Main : BaseUnityPlugin
	{
		[HarmonyPatch]
		public class Patches
		{
			[HarmonyPatch(/*Could not decode attribute arguments.*/)]
			[HarmonyILManipulator]
			private static void SkinDef_ApplyAsync(ILContext il)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Expected O, but got Unknown
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				ILCursor val = new ILCursor(il);
				if (val.TryGotoNext(new Func<Instruction, bool>[3]
				{
					(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, 2),
					(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 1),
					(Instruction x) => ILPatternMatchingExt.MatchStfld<CharacterModel>(x, "forceUpdate")
				}))
				{
					val.Emit(OpCodes.Ldloc_2);
					val.EmitDelegate<Action<CharacterModel>>((Action<CharacterModel>)ForceApply);
				}
				else
				{
					Debug.LogError((object)(((MemberReference)il.Method).Name + " IL Hook failed!"));
				}
			}
		}

		public class ActivePartsComponent : MonoBehaviour
		{
			public List<GameObject> activeGameObjects = new List<GameObject>();

			public List<Component> components = new List<Component>();

			public CharacterModel characterModel;

			public List<ModelPartDef> modelParts = new List<ModelPartDef>();

			public Loadout loadout;

			public BodyIndex bodyIndex;

			public SkinDef skinDef;

			public ChildLocator childLocator;

			public List<SkillDef> skillDefs = new List<SkillDef>();

			public NetworkUser networkUser;

			public Dictionary<GameObject, List<RendererInfo>> keyValuePairs = new Dictionary<GameObject, List<RendererInfo>>();

			public void Start()
			{
			}

			public void ApplyParts()
			{
				ApplyModelParts(modelParts, characterModel, this, skinDef, childLocator, skillDefs);
			}
		}

		public enum ModelPartLocation
		{
			All,
			Lobby,
			Game
		}

		public class ModelPartInfo
		{
			public string bodyName = "";

			public GameObject gameObject = null;

			public string inputString = "";

			public bool trueToChildLocatorFalseToFindString = true;

			public SkinDef skinDef = null;

			public string skinName = "";

			public SkillDef skillDef = null;

			public ModelPart modelPartOverride = null;

			public CodeAfterApplying codeAfterApplying = null;

			public CustomCondition customCondition = null;

			public ModelPartLocation modelPartLocation = ModelPartLocation.All;
		}

		public class ModelPart
		{
			public SkinDef skinDef;

			public GameObject gameObject;

			public string bone = "";

			public SkillDef skill;

			public string skinName = "";

			public ModelPart modelPartOverride;

			public CodeAfterApplying codeAfterApplying;

			public CustomCondition customCondition;

			public bool useChildLocator;

			public ModelPart(ModelPartInfo modelPartInfo)
			{
				ModelPartDef modelPartDef = CreateModelPartDefFromModelPartInfo(modelPartInfo);
				modelPartOverride = modelPartInfo.modelPartOverride;
				modelPartDef.Register();
				backport.Add(this, modelPartDef);
			}
		}

		public delegate void CodeAfterApplying(GameObject modelObject, ChildLocator childLocator, CharacterModel characterModel, ActivePartsComponent activePartsComponent);

		public delegate bool CustomCondition(CharacterModel characterModel);

		public const string ModGuid = "com.brynzananas.bodymodeladditionsapi";

		public const string ModName = "Body Model Additions API";

		public const string ModVer = "2.1.0";

		public static Dictionary<string, Dictionary<ModelPartLocation, List<ModelPartDef>>> bodySkinParts = new Dictionary<string, Dictionary<ModelPartLocation, List<ModelPartDef>>>();

		public static Dictionary<string, string> fixDisplayPrefabsNameTree = new Dictionary<string, string>();

		public static Dictionary<ModelPart, ModelPartDef> backport = new Dictionary<ModelPart, ModelPartDef>();

		public static List<ModelPartDef> allParts = new List<ModelPartDef>();

		public static AssetBundle Assets;

		public static Main instance;

		public static List<ModelPartDef> modelPartDefs = new List<ModelPartDef>();

		private Harmony harmonyPatcher;

		private bool applied = false;

		public static PluginInfo PInfo { get; private set; }

		public static event Action<ActivePartsComponent> beforeApplyingEvent;

		public void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			PInfo = ((BaseUnityPlugin)this).Info;
			instance = this;
			FixNaming();
			SurvivorMannequinSlotController.ApplyLoadoutToMannequinInstance += new hook_ApplyLoadoutToMannequinInstance(SurvivorMannequinSlotController_ApplyLoadoutToMannequinInstance);
			SurvivorCatalog.Init += new hook_Init(SurvivorCatalog_Init);
			harmonyPatcher = new Harmony("com.brynzananas.bodymodeladditionsapi");
			harmonyPatcher.CreateClassProcessor(typeof(Patches)).Patch();
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(AddStuff));
		}

		private void AddStuff()
		{
			foreach (ModelPartDef modelPartDef in modelPartDefs)
			{
				modelPartDef.Register();
			}
		}

		private static void FixNaming()
		{
			fixDisplayPrefabsNameTree.Add("toolbotbody", "Base");
			fixDisplayPrefabsNameTree.Add("treebotbody", "ModelBase");
		}

		private void SurvivorCatalog_Init(orig_Init orig)
		{
			orig.Invoke();
			if (applied)
			{
				return;
			}
			applied = true;
			foreach (SurvivorDef allSurvivorDef in SurvivorCatalog.allSurvivorDefs)
			{
				if (Object.op_Implicit((Object)(object)allSurvivorDef.displayPrefab) && Object.op_Implicit((Object)(object)allSurvivorDef.bodyPrefab))
				{
					bool flag = true;
					ChildLocator componentInChildren = allSurvivorDef.bodyPrefab.GetComponentInChildren<ChildLocator>();
					if ((Object)(object)componentInChildren != (Object)null)
					{
						GenerateChildLocatorForDisplayPrefab(allSurvivorDef.displayPrefab, allSurvivorDef.bodyPrefab, componentInChildren);
					}
				}
			}
		}

		public static void ForceApply(CharacterModel self)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)self))
			{
				return;
			}
			bool flag = true;
			CharacterBody body = self.body;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			BodyIndex bodyIndex = body.bodyIndex;
			string bodyName = BodyCatalog.GetBodyName(bodyIndex);
			if (bodyName == null || !(bodyName != "") || !bodySkinParts.ContainsKey(bodyName) || !bodySkinParts[bodyName].ContainsKey(ModelPartLocation.Game))
			{
				return;
			}
			ChildLocator childLocator = self.childLocator;
			GenericSkill[] array = body.skillLocator?.allSkills;
			List<SkillDef> list = new List<SkillDef>();
			if (array != null)
			{
				GenericSkill[] array2 = array;
				foreach (GenericSkill val in array2)
				{
					list.Add(val.baseSkill);
				}
			}
			SkinDef skinDef = null;
			ModelSkinController component = ((Component)self).GetComponent<ModelSkinController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				skinDef = component.skins[body.skinIndex];
			}
			ActivePartsComponent orAddComponent = ((Component)self).gameObject.GetOrAddComponent<ActivePartsComponent>();
			orAddComponent.modelParts = bodySkinParts[bodyName][ModelPartLocation.Game];
			orAddComponent.characterModel = self;
			orAddComponent.skillDefs = list;
			orAddComponent.skinDef = skinDef;
			orAddComponent.childLocator = childLocator;
			orAddComponent.bodyIndex = bodyIndex;
			orAddComponent.ApplyParts();
		}

		public static void ApplyCharacterModel(CharacterModel self)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)self))
			{
				return;
			}
			ModelSkinController component = ((Component)self).GetComponent<ModelSkinController>();
			if (Object.op_Implicit((Object)(object)component) && component.skins != null && component.skins.Length != 0)
			{
				return;
			}
			CharacterBody body = self.body;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			BodyIndex bodyIndex = body.bodyIndex;
			string bodyName = BodyCatalog.GetBodyName(bodyIndex);
			if (bodyName == null || !(bodyName != "") || !bodySkinParts.ContainsKey(bodyName) || !bodySkinParts[bodyName].ContainsKey(ModelPartLocation.Game))
			{
				return;
			}
			ChildLocator childLocator = self.childLocator;
			GenericSkill[] array = body.skillLocator?.allSkills;
			List<SkillDef> list = new List<SkillDef>();
			if (array != null)
			{
				GenericSkill[] array2 = array;
				foreach (GenericSkill val in array2)
				{
					list.Add(val.baseSkill);
				}
			}
			SkinDef skinDef = null;
			if (Object.op_Implicit((Object)(object)component))
			{
				skinDef = component.skins[body.skinIndex];
			}
			ActivePartsComponent orAddComponent = ((Component)self).gameObject.GetOrAddComponent<ActivePartsComponent>();
			orAddComponent.modelParts = bodySkinParts[bodyName][ModelPartLocation.Game];
			orAddComponent.characterModel = self;
			orAddComponent.skillDefs = list;
			orAddComponent.skinDef = skinDef;
			orAddComponent.childLocator = childLocator;
			orAddComponent.bodyIndex = bodyIndex;
			orAddComponent.ApplyParts();
		}

		private void CharacterModel_Start(orig_Start orig, CharacterModel self)
		{
			ApplyCharacterModel(self);
			orig.Invoke(self);
		}

		private static void GenerateChildLocatorForDisplayPrefab(GameObject displayPrefab, GameObject bodyObject, ChildLocator childLocator)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: 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)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			CharacterModel componentInChildren = displayPrefab.GetComponentInChildren<CharacterModel>();
			if (!((Object)(object)componentInChildren != (Object)null))
			{
				return;
			}
			ChildLocator componentInChildren2 = displayPrefab.GetComponentInChildren<ChildLocator>();
			ChildLocator val = (Object.op_Implicit((Object)(object)componentInChildren2) ? componentInChildren2 : ((Component)componentInChildren).gameObject.GetOrAddComponent<ChildLocator>());
			List<NameTransformPair> list = new List<NameTransformPair>();
			List<string> list2 = new List<string>();
			if (Object.op_Implicit((Object)(object)componentInChildren2))
			{
				list.AddRange(componentInChildren2.transformPairs);
				NameTransformPair[] transformPairs = componentInChildren2.transformPairs;
				foreach (NameTransformPair val2 in transformPairs)
				{
					list2.Add(val2.name);
				}
			}
			CharacterModel component = ((Component)componentInChildren).gameObject.GetComponent<CharacterModel>();
			ModelLocator component2 = bodyObject.GetComponent<ModelLocator>();
			for (int j = 0; j < childLocator.transformPairs.Length; j++)
			{
				NameTransformPair val3 = childLocator.transformPairs[j];
				NameTransformPair item = default(NameTransformPair);
				string inScenePath = GetInScenePath(val3.transform);
				string oldValue = ((Object)bodyObject).name + "/" + (Object.op_Implicit((Object)(object)component2) ? ((Object)component2.modelBaseTransform).name : "") + "/";
				string text = "";
				if (fixDisplayPrefabsNameTree.ContainsKey(((Object)bodyObject).name.ToLower()))
				{
					text = fixDisplayPrefabsNameTree[((Object)bodyObject).name.ToLower()] + "/";
				}
				Transform val4 = displayPrefab.transform.Find(text + inScenePath.Replace(oldValue, ""));
				if ((Object)(object)val4 != (Object)null && !list2.Contains(val3.name))
				{
					item.name = val3.name;
					item.transform = val4;
					list.Add(item);
				}
				else if (!((Object)(object)val4 != (Object)null))
				{
				}
			}
			val.transformPairs = list.ToArray();
		}

		private static string GetInScenePath(Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "null";
			}
			Transform val = transform;
			List<string> list = new List<string> { ((Object)val).name };
			while ((Object)(object)val != (Object)(object)transform.root)
			{
				val = val.parent;
				list.Add(((Object)val).name);
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in Enumerable.Reverse(list))
			{
				stringBuilder.Append("/" + item);
			}
			return stringBuilder.ToString().TrimStart('/');
		}

		private void SurvivorMannequinSlotController_ApplyLoadoutToMannequinInstance(orig_ApplyLoadoutToMannequinInstance orig, SurvivorMannequinSlotController self)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self);
			if (!Object.op_Implicit((Object)(object)self.mannequinInstanceTransform))
			{
				return;
			}
			GameObject bodyPrefab = self.currentSurvivorDef.bodyPrefab;
			string name = ((Object)bodyPrefab).name;
			if (name == null || name == "" || !bodySkinParts.ContainsKey(name) || !bodySkinParts[name].ContainsKey(ModelPartLocation.Lobby))
			{
				return;
			}
			ChildLocator componentInChildren = ((Component)self.mannequinInstanceTransform).GetComponentInChildren<ChildLocator>();
			if (!Object.op_Implicit((Object)(object)self.currentSurvivorDef))
			{
				return;
			}
			BodyIndex bodyIndexFromSurvivorIndex = SurvivorCatalog.GetBodyIndexFromSurvivorIndex(self.currentSurvivorDef.survivorIndex);
			Loadout currentLoadout = self.currentLoadout;
			if (currentLoadout == null || currentLoadout.bodyLoadoutManager == null)
			{
				return;
			}
			BodyLoadout readOnlyBodyLoadout = currentLoadout.bodyLoadoutManager.GetReadOnlyBodyLoadout(bodyIndexFromSurvivorIndex);
			if (readOnlyBodyLoadout == null)
			{
				return;
			}
			currentLoadout.bodyLoadoutManager.GetSkinIndex(bodyIndexFromSurvivorIndex);
			if (false)
			{
				return;
			}
			SkinDef bodySkinDef = SkinCatalog.GetBodySkinDef(bodyIndexFromSurvivorIndex, (int)currentLoadout.bodyLoadoutManager.GetSkinIndex(bodyIndexFromSurvivorIndex));
			CharacterModel componentInChildren2 = ((Component)self.mannequinInstanceTransform).GetComponentInChildren<CharacterModel>();
			GenericSkill[] bodyPrefabSkillSlots = BodyCatalog.GetBodyPrefabSkillSlots(bodyIndexFromSurvivorIndex);
			List<SkillDef> list = new List<SkillDef>();
			if (bodyPrefabSkillSlots != null)
			{
				int num = 0;
				GenericSkill[] array = bodyPrefabSkillSlots;
				foreach (GenericSkill val in array)
				{
					readOnlyBodyLoadout.GetSkillVariant(num);
					if (Object.op_Implicit((Object)(object)val.skillFamily.variants[readOnlyBodyLoadout.GetSkillVariant(num)].skillDef))
					{
						list.Add(val.skillFamily.variants[readOnlyBodyLoadout.GetSkillVariant(num)].skillDef);
					}
					num++;
				}
			}
			ActivePartsComponent orAddComponent = ((Component)componentInChildren2).gameObject.GetOrAddComponent<ActivePartsComponent>();
			orAddComponent.modelParts = bodySkinParts[name][ModelPartLocation.Lobby];
			orAddComponent.characterModel = componentInChildren2;
			orAddComponent.skinDef = bodySkinDef;
			orAddComponent.childLocator = componentInChildren;
			orAddComponent.skillDefs = list;
			orAddComponent.bodyIndex = bodyIndexFromSurvivorIndex;
			orAddComponent.networkUser = self.networkUser;
			orAddComponent.ApplyParts();
		}

		public static void ApplyModelParts(List<ModelPartDef> modelParts, CharacterModel characterModel, ActivePartsComponent activePartsComponent, SkinDef skinDef, ChildLocator childLocator, List<SkillDef> skillDefs)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_054a: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)activePartsComponent))
			{
				if (Main.beforeApplyingEvent != null)
				{
					Main.beforeApplyingEvent(activePartsComponent);
				}
				if (Object.op_Implicit((Object)(object)characterModel))
				{
					List<RendererInfo> list = characterModel.baseRendererInfos.ToList();
					foreach (KeyValuePair<GameObject, List<RendererInfo>> keyValuePair in activePartsComponent.keyValuePairs)
					{
						foreach (RendererInfo item2 in keyValuePair.Value)
						{
							if (list.Contains(item2))
							{
								list.Remove(item2);
							}
						}
					}
					activePartsComponent.keyValuePairs.Clear();
					characterModel.baseRendererInfos = list.ToArray();
				}
				for (int i = 0; i < activePartsComponent.activeGameObjects.Count; i++)
				{
					Object.Destroy((Object)(object)activePartsComponent.activeGameObjects[i]);
				}
				activePartsComponent.activeGameObjects.Clear();
				for (int j = 0; j < activePartsComponent.components.Count; j++)
				{
					Object.Destroy((Object)(object)activePartsComponent.components[j]);
				}
				activePartsComponent.components.Clear();
			}
			List<GameObject> list2 = new List<GameObject>();
			List<ModelPartDef> list3 = new List<ModelPartDef>();
			foreach (ModelPartDef modelPart in modelParts)
			{
				bool flag = false;
				if (modelPart.skillDefs != null && modelPart.skillDefs.Count > 0)
				{
					foreach (SkillDef skillDef in skillDefs)
					{
						if ((Object)(object)skillDef == (Object)null || !modelPart.skillDefs.Contains(skillDef))
						{
							continue;
						}
						flag = true;
						break;
					}
				}
				bool num;
				if (modelPart.skinDefs == null || modelPart.skinDefs.Count <= 0)
				{
					if (modelPart.skinName != "")
					{
						num = modelPart.skinName == ((Object)skinDef).name;
						goto IL_0268;
					}
				}
				else if (Object.op_Implicit((Object)(object)skinDef))
				{
					num = modelPart.skinDefs.Contains(skinDef);
					goto IL_0268;
				}
				goto IL_026a;
				IL_026a:
				if ((modelPart.skillDefs == null || modelPart.skillDefs.Count <= 0 || flag) && (modelPart.customCondition == null || modelPart.customCondition(characterModel)))
				{
					if ((Object)(object)modelPart.modelPartOverride != (Object)null && list3.Contains(modelPart.modelPartOverride))
					{
						list3.Remove(modelPart.modelPartOverride);
					}
					list3.Add(modelPart);
				}
				continue;
				IL_0268:
				if (!num)
				{
					continue;
				}
				goto IL_026a;
			}
			foreach (ModelPartDef item3 in list3)
			{
				Transform val = ((!(item3.inputString != "")) ? ((Component)characterModel).transform : ((!item3.trueToChildLocatorFalseToFindString) ? (Object.op_Implicit((Object)(object)((Component)characterModel).transform.Find(item3.inputString)) ? ((Component)characterModel).transform.Find(item3.inputString) : ((Component)characterModel).transform) : ((!Object.op_Implicit((Object)(object)childLocator)) ? ((Component)characterModel).transform : (Object.op_Implicit((Object)(object)childLocator.FindChild(item3.inputString)) ? childLocator.FindChild(item3.inputString) : ((Component)characterModel).transform))));
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				GameObject val2 = (Object.op_Implicit((Object)(object)item3.gameObject) ? Object.Instantiate<GameObject>(item3.gameObject, val) : null);
				item3.codeAfterApplying?.Invoke(val2, childLocator, characterModel, activePartsComponent);
				if ((Object)(object)val2 != (Object)null)
				{
					list2.Add(val2);
					if (Object.op_Implicit((Object)(object)activePartsComponent))
					{
						activePartsComponent.activeGameObjects.Add(val2);
					}
				}
			}
			List<RendererInfo> list4 = characterModel.baseRendererInfos.ToList();
			foreach (GameObject item4 in list2)
			{
				Renderer[] componentsInChildren = item4.GetComponentsInChildren<Renderer>();
				Renderer[] array = componentsInChildren;
				foreach (Renderer val3 in array)
				{
					if (!((Object)(object)val3 != (Object)null))
					{
						continue;
					}
					RendererInfo val4 = default(RendererInfo);
					val4.defaultMaterial = val3.material;
					val4.defaultShadowCastingMode = val3.shadowCastingMode;
					val4.hideOnDeath = false;
					val4.ignoreOverlays = false;
					val4.renderer = val3;
					RendererInfo item = val4;
					if (Object.op_Implicit((Object)(object)activePartsComponent))
					{
						if (activePartsComponent.keyValuePairs.ContainsKey(item4))
						{
							activePartsComponent.keyValuePairs[item4].Add(item);
						}
						else
						{
							List<RendererInfo> list5 = new List<RendererInfo>();
							list5.Add(item);
							activePartsComponent.keyValuePairs.Add(item4, list5);
						}
					}
					list4.Add(item);
				}
			}
			characterModel.baseRendererInfos = list4.ToArray();
			characterModel.forceUpdate = true;
		}

		private void ModelSkinController_ApplySkin(orig_ApplySkin orig, ModelSkinController self, int skinIndex)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, skinIndex);
			if (!Object.op_Implicit((Object)(object)self.characterModel))
			{
				return;
			}
			CharacterBody body = self.characterModel.body;
			if (!Object.op_Implicit((Object)(object)body))
			{
				return;
			}
			BodyIndex bodyIndex = body.bodyIndex;
			string bodyName = BodyCatalog.GetBodyName(bodyIndex);
			SkinDef bodySkinDef = SkinCatalog.GetBodySkinDef(body.bodyIndex, skinIndex);
			if (!bodySkinParts.ContainsKey(bodyName) || !bodySkinParts[bodyName].ContainsKey(ModelPartLocation.Game))
			{
				return;
			}
			ActivePartsComponent orAddComponent = ((Component)self).gameObject.GetOrAddComponent<ActivePartsComponent>();
			ChildLocator childLocator = self.characterModel.childLocator;
			GenericSkill[] array = body.skillLocator?.allSkills;
			List<SkillDef> list = new List<SkillDef>();
			if (array != null)
			{
				GenericSkill[] array2 = array;
				foreach (GenericSkill val in array2)
				{
					list.Add(val.baseSkill);
				}
			}
			ApplyModelParts(bodySkinParts[bodyName][ModelPartLocation.Game], self.characterModel, orAddComponent, bodySkinDef, childLocator, list);
		}

		public static void RegisterModelPartDef(ModelPartDef modelPartDef, ModelPartLocation modelPartLocation)
		{
			if (bodySkinParts.ContainsKey(modelPartDef.bodyName))
			{
				if (bodySkinParts[modelPartDef.bodyName].ContainsKey(modelPartLocation))
				{
					bodySkinParts[modelPartDef.bodyName][modelPartLocation].Add(modelPartDef);
				}
				else
				{
					List<ModelPartDef> list = new List<ModelPartDef>();
					list.Add(modelPartDef);
					bodySkinParts[modelPartDef.bodyName].Add(modelPartLocation, list);
				}
			}
			else
			{
				Dictionary<ModelPartLocation, List<ModelPartDef>> dictionary = new Dictionary<ModelPartLocation, List<ModelPartDef>>();
				List<ModelPartDef> list2 = new List<ModelPartDef>();
				list2.Add(modelPartDef);
				dictionary.Add(modelPartLocation, list2);
				bodySkinParts.Add(modelPartDef.bodyName, dictionary);
			}
			allParts.Add(modelPartDef);
		}

		public static ModelPartDef CreateModelPartDefFromModelPartInfo(ModelPartInfo modelPartInfo)
		{
			ModelPartDef modelPartDef = ScriptableObject.CreateInstance<ModelPartDef>();
			if (Object.op_Implicit((Object)(object)modelPartInfo.skillDef))
			{
				modelPartDef.skillDefs.Add(modelPartInfo.skillDef);
			}
			if (Object.op_Implicit((Object)(object)modelPartInfo.skinDef))
			{
				modelPartDef.skinDefs.Add(modelPartInfo.skinDef);
			}
			modelPartDef.bodyName = modelPartInfo.bodyName;
			modelPartDef.codeAfterApplying = modelPartInfo.codeAfterApplying;
			modelPartDef.customCondition = modelPartInfo.customCondition;
			modelPartDef.gameObject = modelPartInfo.gameObject;
			modelPartDef.inputString = modelPartInfo.inputString;
			modelPartDef.modelPartLocation = modelPartInfo.modelPartLocation;
			modelPartDef.modelPartOverride = ((modelPartInfo.modelPartOverride != null && backport.ContainsKey(modelPartInfo.modelPartOverride)) ? backport[modelPartInfo.modelPartOverride] : null);
			modelPartDef.skinName = modelPartInfo.skinName;
			return modelPartDef;
		}
	}
	public static class Extensions
	{
		public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
		{
			T component = gameObject.GetComponent<T>();
			if (Object.op_Implicit((Object)(object)component))
			{
				return component;
			}
			Component obj = gameObject.AddComponent(typeof(T));
			return (T)(object)((obj is T) ? obj : null);
		}

		public static string GetInScenePath(this Transform transform)
		{
			if ((Object)(object)transform == (Object)null)
			{
				return "null";
			}
			Transform val = transform;
			List<string> list = new List<string> { ((Object)val).name };
			while ((Object)(object)val != (Object)(object)transform.root)
			{
				val = val.parent;
				list.Add(((Object)val).name);
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (string item in Enumerable.Reverse(list))
			{
				stringBuilder.Append("/" + item);
			}
			return stringBuilder.ToString().TrimStart('/');
		}
	}
	[CreateAssetMenu(menuName = "BodyModelAdditions/ModelPartDef")]
	public class ModelPartDef : ScriptableObject
	{
		public string bodyName = "";

		public GameObject gameObject = null;

		public string inputString = "";

		public bool trueToChildLocatorFalseToFindString = true;

		[SerializeField]
		public List<SkinDef> skinDefs = new List<SkinDef>();

		public string skinName = "";

		[SerializeField]
		public List<SkillDef> skillDefs = new List<SkillDef>();

		public ModelPartDef modelPartOverride = null;

		[SerializeField]
		public Main.CodeAfterApplying codeAfterApplying = null;

		[SerializeField]
		public Main.CustomCondition customCondition = null;

		public Main.ModelPartLocation modelPartLocation = Main.ModelPartLocation.All;

		private bool registered = false;

		public void Register()
		{
			if (!registered)
			{
				registered = true;
				if (modelPartLocation == Main.ModelPartLocation.All)
				{
					Main.RegisterModelPartDef(this, Main.ModelPartLocation.Lobby);
					Main.RegisterModelPartDef(this, Main.ModelPartLocation.Game);
				}
				else
				{
					Main.RegisterModelPartDef(this, modelPartLocation);
				}
			}
		}
	}
}