Decompiled source of Rodanius Skin Runtime v0.1.1

BepInEx/plugins/RodaniusSkinRuntime/Eclipse.LoaderSkins.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using EclipseSkinRuntimeFix;
using EntityStates;
using HG.Reflection;
using On.RoR2.Projectile;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Projectile;
using RoR2.UI.MainMenu;
using Rodanius.Standalone;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: AssemblyVersion("0.0.0.0")]
namespace EclipseSkinRuntimeFix
{
	internal static class NativeRenderers
	{
		private static readonly HashSet<string> NativePaths = new HashSet<string>(StringComparer.Ordinal)
		{
			"mdlLoader/PilotFemaleMesh", "mdlLoader/LoaderMechMesh", "mdlLoader/PilotFemaleFoldedOverJumpsuit", "mdlFalseSon/FalseSon_Body", "mdlFalseSon/FalseSon_Cloth", "mdlFalseSon/L_FalseSon_Weapon", "mdlSeeker/meshSeekerBody", "mdlSeeker/meshSeekerCloth", "mdlSeeker/meshSeekerGlass", "mdlChef/meshChef",
			"mdlChef/meshChefPizzaCutter", "mdlChef/meshlChefCleaver", "mdlChef/meshChefOven", "mdlChef/meshChefIceBox", "mdlCroco/CrocoMesh", "mdlCroco/CrocoSpineMesh", "mdlHuntress/HuntressMesh", "mdlHuntress/BowMesh", "mdlHuntress/HuntressScarfMesh", "mdlHuntress (1)/HuntressMesh",
			"mdlHuntress (1)/BowMesh", "mdlHuntress (1)/HuntressScarfMesh", "mdlMerc/MercMesh", "mdlMerc/MercSwordMesh", "mdlTreebot/TreebotBotMesh", "mdlTreebot/TreebotRootMesh", "mdlTreebot/TreebotLeafletMesh", "mdlTreebot/TreebotFlowerMesh", "mdlVoidSurvivor/mdlVoidSurvivorBody", "mdlVoidSurvivor/mdlVoidSurvivorHead",
			"mdlVoidSurvivor/mdlVoidSurvivorMetal", "mdlVoidSurvivor/metalcollar.001", "mdlBandit2/BanditArmature/ROOT/base/MainWeapon/BanditShotgunMesh", "mdlBandit2/BanditArmature/SideWeapon/SideWeaponSpinner/BanditPistolMesh", "mdlBandit2/Bandit2AccessoriesMesh"
		};

		public static T[] GetSkinRenderers<T>(this Component owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer
		{
			return owner.gameObject.GetSkinRenderers<T>(inactive, parameters);
		}

		public static T[] GetSkinRenderers<T>(this GameObject owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			T[] componentsInChildren = owner.GetComponentsInChildren<T>(inactive);
			CharacterModel val = owner.GetComponent<CharacterModel>() ?? owner.GetComponentInParent<CharacterModel>();
			ModelSkinController val2 = owner.GetComponent<ModelSkinController>() ?? (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelSkinController>() : null);
			HashSet<Renderer> skinRefs = new HashSet<Renderer>();
			SkinDefParams val3 = parameters;
			if (!Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val2) && val2.skins != null && val2.skins.Length != 0 && Object.op_Implicit((Object)(object)val2.skins[0]))
			{
				val3 = val2.skins[0].skinDefParams;
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				if (val3.rendererInfos != null)
				{
					RendererInfo[] rendererInfos = val3.rendererInfos;
					foreach (RendererInfo val4 in rendererInfos)
					{
						if (Object.op_Implicit((Object)(object)val4.renderer))
						{
							skinRefs.Add(val4.renderer);
						}
					}
				}
				if (val3.meshReplacements != null)
				{
					MeshReplacement[] meshReplacements = val3.meshReplacements;
					foreach (MeshReplacement val5 in meshReplacements)
					{
						if (Object.op_Implicit((Object)(object)val5.renderer))
						{
							skinRefs.Add(val5.renderer);
						}
					}
				}
			}
			HashSet<Renderer> modelRefs = new HashSet<Renderer>();
			if (Object.op_Implicit((Object)(object)val) && val.baseRendererInfos != null)
			{
				RendererInfo[] rendererInfos = val.baseRendererInfos;
				foreach (RendererInfo val6 in rendererInfos)
				{
					if (Object.op_Implicit((Object)(object)val6.renderer))
					{
						modelRefs.Add(val6.renderer);
					}
				}
			}
			return Select(componentsInChildren, (T x) => ((Object)(object)x).name, (T x) => skinRefs.Contains((Renderer)(object)x), (T x) => modelRefs.Contains((Renderer)(object)x), (T x) => Path(((Component)(object)x).transform, owner.transform), (T x) => IsKnownNativePath(Path(((Component)(object)x).transform, owner.transform)));
		}

		internal static T[] Select<T>(T[] found, Func<T, string> name, Func<T, bool> skin, Func<T, bool> model, Func<T, string> path, Func<T, bool> contract = null)
		{
			HashSet<T> hashSet = new HashSet<T>();
			if (contract == null)
			{
				contract = (T x) => false;
			}
			bool flag = found.Any(skin) || found.Any(model) || found.Any(contract);
			foreach (IGrouping<string, T> item in found.GroupBy(name))
			{
				T[] array = item.ToArray();
				if (array.Length == 1)
				{
					if (!flag || skin(array[0]) || model(array[0]) || contract(array[0]))
					{
						hashSet.Add(array[0]);
					}
					continue;
				}
				T[] array2 = array.Where(skin).ToArray();
				T[] array3 = array.Where(model).ToArray();
				T[] array4 = ((array2.Length == 1) ? ((array3.Length == 0 || array3.Contains(array2[0])) ? array2 : new T[0]) : ((array2.Length <= 1) ? array3 : array2.Where(((IEnumerable<T>)array3).Contains<T>).ToArray()));
				if (array2.Length == 0 && array3.Length == 0)
				{
					T[] array5 = array.Where(contract).ToArray();
					if (array5.Length != 0)
					{
						if (array5.Length != 1)
						{
							throw new InvalidOperationException("ECLIPSE_RENDERER_PATH_AMBIGUOUS " + string.Join(";", array.Select(path)));
						}
						hashSet.Add(array5[0]);
						Debug.Log((object)("ECLIPSE_RENDERER_NATIVE_PATH name=" + item.Key + " native=" + path(array5[0])));
						continue;
					}
				}
				if (array2.Length == 0 && array3.Length == 0 && flag)
				{
					Debug.Log((object)("ECLIPSE_RENDERER_FOREIGN_DUPLICATES name=" + item.Key + " ignored=" + array.Length));
					continue;
				}
				if (array4.Length != 1)
				{
					throw new InvalidOperationException("ECLIPSE_RENDERER_AMBIGUOUS name=" + item.Key + " candidates=" + string.Join(";", array.Select(path)) + " skinRefs=" + array2.Length + " modelRefs=" + array3.Length);
				}
				hashSet.Add(array4[0]);
				Debug.Log((object)("ECLIPSE_RENDERER_RESOLVED name=" + item.Key + " native=" + path(array4[0]) + " ignoredDuplicates=" + (array.Length - 1)));
			}
			return found.Where(hashSet.Contains).ToArray();
		}

		internal static bool IsKnownNativePath(string path)
		{
			if (path == null)
			{
				return false;
			}
			int num = path.IndexOf('/');
			if (num < 0)
			{
				return false;
			}
			string text = path.Substring(0, num);
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = text.Substring(0, text.Length - 7);
			}
			return NativePaths.Contains(text + path.Substring(num));
		}

		private static string Path(Transform t, Transform root)
		{
			List<string> list = new List<string>();
			Transform val = t;
			while (Object.op_Implicit((Object)(object)val))
			{
				list.Add(((Object)val).name);
				if ((Object)(object)val == (Object)(object)root)
				{
					break;
				}
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}
	}
}
namespace Eclipse.LoaderSkins
{
	internal sealed class LoaderBearClearance
	{
		private readonly Transform space;

		private readonly Transform head;

		private readonly Transform[] a = (Transform[])(object)new Transform[2];

		private readonly Transform[] b = (Transform[])(object)new Transform[2];

		private readonly Transform[] c = (Transform[])(object)new Transform[2];

		private readonly Vector3[] paw = (Vector3[])(object)new Vector3[2];

		private readonly Vector3 neck;

		private readonly Vector3 skull;

		private readonly CharacterBody body;

		public LoaderBearClearance(Transform model, Transform rendererSpace, Transform[] visual, LoaderRig rig)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: 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_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			space = rendererSpace;
			body = ((Component)model).GetComponentInParent<CharacterBody>();
			int num = Find(rig, "head");
			head = visual[num];
			neck = Local(rig, num, new Vector3(0f, 0.1f, 1.75f));
			skull = Local(rig, num, new Vector3(0f, -0.035f, 2.4f));
			for (int i = 0; i < 2; i++)
			{
				string text = ((i == 0) ? "l" : "r");
				int num2 = Find(rig, "mech.upper_arm." + text);
				int num3 = Find(rig, "mech.lower_arm." + text);
				int num4 = Find(rig, "mech.hand." + text);
				a[i] = visual[num2];
				b[i] = visual[num3];
				c[i] = visual[num4];
				Matrix4x4 val = Bind(rig, num4);
				Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
				Vector3 val2 = Vector4.op_Implicit(((Matrix4x4)(ref inverse)).GetColumn(3));
				paw[i] = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val2 + new Vector3((i == 0) ? (-0.08f) : 0.08f, -0.025f, -0.16f));
			}
		}

		private static int Find(LoaderRig rig, string name)
		{
			for (int i = 0; i < rig.bones.Length; i++)
			{
				if (rig.bones[i].name == name)
				{
					return i;
				}
			}
			throw new InvalidOperationException("Missing bear bone " + name);
		}

		private static Matrix4x4 Bind(LoaderRig rig, int i)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 result = default(Matrix4x4);
			for (int j = 0; j < 16; j++)
			{
				((Matrix4x4)(ref result))[j / 4, j % 4] = rig.bones[i].bindpose[j];
			}
			return result;
		}

		private static Vector3 Local(LoaderRig rig, int i, Vector3 point)
		{
			//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_000a: 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)
			Matrix4x4 val = Bind(rig, i);
			return ((Matrix4x4)(ref val)).MultiplyPoint3x4(point);
		}

		public void Apply()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//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_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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)
			//IL_0109: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: 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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: 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)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_045b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_037f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_0385: Unknown result type (might be due to invalid IL or missing references)
			//IL_038a: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0394: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_039e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0409: Unknown result type (might be due to invalid IL or missing references)
			//IL_040e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0413: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_043e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0445: Unknown result type (might be due to invalid IL or missing references)
			//IL_044a: Unknown result type (might be due to invalid IL or missing references)
			//IL_044c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0451: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && !body.healthComponent.alive)
			{
				return;
			}
			Vector3 val = head.TransformPoint(neck);
			Vector3 val2 = head.TransformPoint(skull) - val;
			float num = 0.68f * Mathf.Max(new float[3]
			{
				Mathf.Abs(space.lossyScale.x),
				Mathf.Abs(space.lossyScale.y),
				Mathf.Abs(space.lossyScale.z)
			});
			for (int i = 0; i < 2; i++)
			{
				Vector3 val3 = c[i].TransformPoint(paw[i]);
				Vector3 val4 = val + val2 * Mathf.Clamp01(Vector3.Dot(val3 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
				Vector3 val5 = val3 - val4;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				if (magnitude >= num)
				{
					continue;
				}
				float num2 = Mathf.SmoothStep(0f, 1f, (num - magnitude) / (0.2f * num / 0.68f));
				Vector3 val6 = space.TransformDirection(new Vector3((i == 0) ? (-0.25f) : 0.25f, 0f, 0f)) * num2;
				Vector3 val7 = val5 + val6;
				Vector3 val8 = ((Vector3)(ref val7)).normalized;
				if (((Vector3)(ref val8)).sqrMagnitude < 0.5f)
				{
					val8 = space.TransformDirection((i == 0) ? Vector3.left : Vector3.right);
				}
				Vector3 val9 = c[i].position + (val4 + val8 * num - val3);
				val7 = b[i].position - a[i].position;
				float magnitude2 = ((Vector3)(ref val7)).magnitude;
				val7 = c[i].position - b[i].position;
				float num3 = magnitude2 + ((Vector3)(ref val7)).magnitude - 0.0005f;
				val7 = val9 - a[i].position;
				if (((Vector3)(ref val7)).magnitude > num3)
				{
					Vector3 val10 = a[i].position + val3 - c[i].position;
					Vector3 val11 = val + val2 * Mathf.Clamp01(Vector3.Dot(val10 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
					val7 = val10 - val11;
					Vector3 val12 = ((Vector3)(ref val7)).normalized;
					if (((Vector3)(ref val12)).sqrMagnitude < 0.5f)
					{
						val12 = space.TransformDirection((i == 0) ? Vector3.left : Vector3.right);
					}
					Vector3 val13 = val11 + val12 * num;
					Vector3 val14 = val4 + val8 * num;
					float num4 = 0f;
					float num5 = 1f;
					for (int j = 0; j < 14; j++)
					{
						float num6 = (num4 + num5) * 0.5f;
						Vector3 val15 = Vector3.Lerp(val14, val13, num6);
						Vector3 val16 = val + val2 * Mathf.Clamp01(Vector3.Dot(val15 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
						val7 = val15 - val16;
						val15 = val16 + ((Vector3)(ref val7)).normalized * num;
						val7 = val15 - val10;
						if (((Vector3)(ref val7)).magnitude <= num3 - 0.0001f)
						{
							num5 = num6;
						}
						else
						{
							num4 = num6;
						}
					}
					Vector3 val17 = Vector3.Lerp(val14, val13, num5);
					Vector3 val18 = val + val2 * Mathf.Clamp01(Vector3.Dot(val17 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
					val7 = val17 - val18;
					val17 = val18 + ((Vector3)(ref val7)).normalized * num;
					val9 = c[i].position + val17 - val3;
				}
				Quaternion rotation = c[i].rotation;
				Solve(i, val9, rotation);
			}
		}

		private void Solve(int s, Vector3 target, Quaternion orientation)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			Vector3 position = a[s].position;
			Vector3 val = b[s].position - position;
			Vector3 val2 = c[s].position - b[s].position;
			Vector3 val3 = target - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float magnitude2 = ((Vector3)(ref val2)).magnitude;
			float magnitude3 = ((Vector3)(ref val3)).magnitude;
			if (!(magnitude < 0.001f) && !(magnitude2 < 0.001f) && !(magnitude3 < 0.001f))
			{
				float num = Mathf.Clamp(magnitude3, Mathf.Abs(magnitude - magnitude2) + 0.0005f, magnitude + magnitude2 - 0.0005f);
				Vector3 val4 = val3 / magnitude3;
				Vector3 val5 = Vector3.ProjectOnPlane(val, val4);
				if (((Vector3)(ref val5)).sqrMagnitude < 1E-05f)
				{
					val5 = Vector3.ProjectOnPlane(space.TransformDirection(new Vector3((s == 0) ? (-0.5f) : 0.5f, 0.4f, 0.1f)), val4);
				}
				Vector3 normalized = ((Vector3)(ref val5)).normalized;
				if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.5f))
				{
					float num2 = (magnitude * magnitude + num * num - magnitude2 * magnitude2) / (2f * num);
					float num3 = Mathf.Sqrt(Mathf.Max(0f, magnitude * magnitude - num2 * num2));
					Vector3 val6 = position + val4 * num2 + normalized * num3;
					a[s].rotation = Quaternion.FromToRotation(val, val6 - position) * a[s].rotation;
					b[s].rotation = Quaternion.FromToRotation(c[s].position - b[s].position, position + val4 * num - b[s].position) * b[s].rotation;
					c[s].rotation = orientation;
				}
			}
		}
	}
	internal sealed class LoaderBowlingClearance
	{
		private readonly Transform space;

		private readonly Transform head;

		private readonly Transform[] centers = (Transform[])(object)new Transform[2];

		private readonly Transform[] a = (Transform[])(object)new Transform[2];

		private readonly Transform[] b = (Transform[])(object)new Transform[2];

		private readonly Transform[] c = (Transform[])(object)new Transform[2];

		private readonly Vector3[] paw = (Vector3[])(object)new Vector3[2];

		private readonly Vector3 neck;

		private readonly Vector3 skull;

		private readonly CharacterBody body;

		public LoaderBowlingClearance(Transform model, Transform rendererSpace, Transform[] visual, LoaderRig rig)
		{
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			space = rendererSpace;
			body = ((Component)model).GetComponentInParent<CharacterBody>();
			int num = Find(rig, "chest");
			head = visual[num];
			neck = Local(rig, num, new Vector3(0f, 0.065f, 1.33f));
			skull = Local(rig, num, new Vector3(0f, 0.065f, 1.33f));
			for (int i = 0; i < 2; i++)
			{
				string text = ((i == 0) ? "l" : "r");
				int num2 = Find(rig, "mech.upper_arm." + text);
				int num3 = Find(rig, "mech.lower_arm." + text);
				int num4 = Find(rig, "mech.hand." + text);
				a[i] = visual[num2];
				b[i] = visual[num3];
				c[i] = visual[num4];
				int num5 = Find(rig, "mech.hand.end." + text);
				centers[i] = visual[num5];
				Matrix4x4 val = Bind(rig, num5);
				Matrix4x4 val2 = Bind(rig, num4);
				val2 = ((Matrix4x4)(ref val2)).inverse;
				Vector3 val3 = Vector4.op_Implicit(((Matrix4x4)(ref val2)).GetColumn(3));
				paw[i] = ((Matrix4x4)(ref val)).MultiplyPoint3x4(val3 + new Vector3((i == 0) ? 0.07f : (-0.07f), -0.086f, 0.066f));
			}
		}

		private static float MaxScale(Transform t)
		{
			//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_000f: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			Vector3 lossyScale = t.lossyScale;
			return Mathf.Max(new float[3]
			{
				Mathf.Abs(lossyScale.x),
				Mathf.Abs(lossyScale.y),
				Mathf.Abs(lossyScale.z)
			});
		}

		private static int Find(LoaderRig rig, string name)
		{
			for (int i = 0; i < rig.bones.Length; i++)
			{
				if (rig.bones[i].name == name)
				{
					return i;
				}
			}
			throw new InvalidOperationException("Missing bowling bone " + name);
		}

		private static Matrix4x4 Bind(LoaderRig rig, int i)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			Matrix4x4 result = default(Matrix4x4);
			for (int j = 0; j < 16; j++)
			{
				((Matrix4x4)(ref result))[j / 4, j % 4] = rig.bones[i].bindpose[j];
			}
			return result;
		}

		private static Vector3 Local(LoaderRig rig, int i, Vector3 point)
		{
			//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_000a: 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)
			Matrix4x4 val = Bind(rig, i);
			return ((Matrix4x4)(ref val)).MultiplyPoint3x4(point);
		}

		public void Apply()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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)
			//IL_0106: 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_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Unknown result type (might be due to invalid IL or missing references)
			//IL_0465: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0304: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_034b: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_0379: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0380: Unknown result type (might be due to invalid IL or missing references)
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_0384: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_0415: Unknown result type (might be due to invalid IL or missing references)
			//IL_0417: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_042d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_0442: Unknown result type (might be due to invalid IL or missing references)
			//IL_0447: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Unknown result type (might be due to invalid IL or missing references)
			//IL_0455: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && !body.healthComponent.alive)
			{
				return;
			}
			Vector3 val = head.TransformPoint(neck);
			Vector3 val2 = head.TransformPoint(skull) - val;
			float num = MaxScale(space);
			float num2 = 0.49f * MaxScale(head);
			for (int i = 0; i < 2; i++)
			{
				float num3 = MaxScale(centers[i]);
				if (num3 < 0.01f)
				{
					continue;
				}
				float num4 = num2 + 0.33f * num3 + 0.025f * num;
				Vector3 val3 = centers[i].TransformPoint(paw[i]);
				Vector3 val4 = val + val2 * Mathf.Clamp01(Vector3.Dot(val3 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
				Vector3 val5 = val3 - val4;
				float magnitude = ((Vector3)(ref val5)).magnitude;
				if (magnitude >= num4)
				{
					continue;
				}
				float num5 = Mathf.SmoothStep(0f, 1f, (num4 - magnitude) / (0.2f * num));
				Vector3 val6 = space.TransformDirection(new Vector3((i == 0) ? (-0.25f) : 0.25f, 0f, 0f)) * num5;
				Vector3 val7 = val5 + val6;
				Vector3 val8 = ((Vector3)(ref val7)).normalized;
				if (((Vector3)(ref val8)).sqrMagnitude < 0.5f)
				{
					val8 = space.TransformDirection((i == 0) ? Vector3.left : Vector3.right);
				}
				Vector3 val9 = c[i].position + (val4 + val8 * num4 - val3);
				val7 = b[i].position - a[i].position;
				float magnitude2 = ((Vector3)(ref val7)).magnitude;
				val7 = c[i].position - b[i].position;
				float num6 = magnitude2 + ((Vector3)(ref val7)).magnitude - 0.0005f;
				val7 = val9 - a[i].position;
				if (((Vector3)(ref val7)).magnitude > num6)
				{
					Vector3 val10 = a[i].position + val3 - c[i].position;
					Vector3 val11 = val + val2 * Mathf.Clamp01(Vector3.Dot(val10 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
					val7 = val10 - val11;
					Vector3 val12 = ((Vector3)(ref val7)).normalized;
					if (((Vector3)(ref val12)).sqrMagnitude < 0.5f)
					{
						val12 = space.TransformDirection((i == 0) ? Vector3.left : Vector3.right);
					}
					Vector3 val13 = val11 + val12 * num4;
					Vector3 val14 = val4 + val8 * num4;
					float num7 = 0f;
					float num8 = 1f;
					for (int j = 0; j < 14; j++)
					{
						float num9 = (num7 + num8) * 0.5f;
						Vector3 val15 = Vector3.Lerp(val14, val13, num9);
						Vector3 val16 = val + val2 * Mathf.Clamp01(Vector3.Dot(val15 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
						val7 = val15 - val16;
						val15 = val16 + ((Vector3)(ref val7)).normalized * num4;
						val7 = val15 - val10;
						if (((Vector3)(ref val7)).magnitude <= num6 - 0.0001f)
						{
							num8 = num9;
						}
						else
						{
							num7 = num9;
						}
					}
					Vector3 val17 = Vector3.Lerp(val14, val13, num8);
					Vector3 val18 = val + val2 * Mathf.Clamp01(Vector3.Dot(val17 - val, val2) / Mathf.Max(((Vector3)(ref val2)).sqrMagnitude, 1E-05f));
					val7 = val17 - val18;
					val17 = val18 + ((Vector3)(ref val7)).normalized * num4;
					val9 = c[i].position + val17 - val3;
				}
				Quaternion rotation = c[i].rotation;
				Solve(i, val9, rotation);
			}
		}

		private void Solve(int s, Vector3 target, Quaternion orientation)
		{
			//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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: 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_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: 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)
			Vector3 position = a[s].position;
			Vector3 val = b[s].position - position;
			Vector3 val2 = c[s].position - b[s].position;
			Vector3 val3 = target - position;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float magnitude2 = ((Vector3)(ref val2)).magnitude;
			float magnitude3 = ((Vector3)(ref val3)).magnitude;
			if (!(magnitude < 0.001f) && !(magnitude2 < 0.001f) && !(magnitude3 < 0.001f))
			{
				float num = Mathf.Clamp(magnitude3, Mathf.Abs(magnitude - magnitude2) + 0.0005f, magnitude + magnitude2 - 0.0005f);
				Vector3 val4 = val3 / magnitude3;
				Vector3 val5 = Vector3.ProjectOnPlane(val, val4);
				if (((Vector3)(ref val5)).sqrMagnitude < 1E-05f)
				{
					val5 = Vector3.ProjectOnPlane(space.TransformDirection(new Vector3((s == 0) ? (-0.5f) : 0.5f, 0.4f, 0.1f)), val4);
				}
				Vector3 normalized = ((Vector3)(ref val5)).normalized;
				if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.5f))
				{
					float num2 = (magnitude * magnitude + num * num - magnitude2 * magnitude2) / (2f * num);
					float num3 = Mathf.Sqrt(Mathf.Max(0f, magnitude * magnitude - num2 * num2));
					Vector3 val6 = position + val4 * num2 + normalized * num3;
					a[s].rotation = Quaternion.FromToRotation(val, val6 - position) * a[s].rotation;
					b[s].rotation = Quaternion.FromToRotation(c[s].position - b[s].position, position + val4 * num - b[s].position) * b[s].rotation;
					c[s].rotation = orientation;
				}
			}
		}
	}
	[BepInPlugin("eclipseplaytest.loader.collection", "Eclipse Loader Skins (Private Playtest)", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class LoaderCollection : BaseUnityPlugin
	{
		[Serializable]
		public sealed class Manifest
		{
			public int schema;

			public Tier[] tiers;
		}

		[Serializable]
		public sealed class Tier
		{
			public int tier;

			public string name;

			public string folder;
		}

		public const string Guid = "eclipseplaytest.loader.collection";

		public const string Version = "0.2.0";

		public static readonly Dictionary<Mesh, LoaderDefinition> ByMesh = new Dictionary<Mesh, LoaderDefinition>();

		public static readonly Dictionary<string, LoaderDefinition> BySkin = new Dictionary<string, LoaderDefinition>();

		public static readonly Dictionary<int, string> ProjectileKinds = new Dictionary<int, string>();

		private static LoaderCollection instance;

		private string folder;

		private float deadline;

		private GameObject model;

		private GameObject display;

		private bool registered;

		private readonly List<AsyncOperationHandle> handles = new List<AsyncOperationHandle>();

		private void Awake()
		{
			instance = this;
			folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(LoaderCollection));
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplay));
			MainMenuController.OnMainMenuInitialised += SyncDisplay;
		}

		[SystemInitializer(new Type[]
		{
			typeof(BodyCatalog),
			typeof(SurvivorCatalog),
			typeof(ProjectileCatalog)
		})]
		private static IEnumerator Initialize()
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				yield break;
			}
			instance.deadline = Time.realtimeSinceStartup + 90f;
			IEnumerator e = instance.Register();
			try
			{
				while (true)
				{
					bool flag;
					try
					{
						flag = e.MoveNext();
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)instance).Logger.LogError((object)("ECLIPSE_LOADER_REGISTRATION_FAILED " + ex));
						break;
					}
					if (flag)
					{
						yield return e.Current;
						continue;
					}
					break;
				}
			}
			finally
			{
				IDisposable disposable = e as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
		}

		private IEnumerator Load<T>(object key, Action<T> set) where T : Object
		{
			AsyncOperationHandle<T> op = Addressables.LoadAssetAsync<T>(key);
			handles.Add(AsyncOperationHandle<T>.op_Implicit(op));
			while (!op.IsDone)
			{
				if (Time.realtimeSinceStartup > deadline)
				{
					throw new TimeoutException("Loader asset loading exceeded deadline");
				}
				yield return null;
			}
			if (!Object.op_Implicit((Object)(object)op.Result))
			{
				throw new InvalidDataException("Missing Loader native asset " + key);
			}
			set(op.Result);
		}

		private IEnumerator Register()
		{
			List<SkinRecord> list = SkinDiscovery.Load("loader", delegate(string m)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)m);
			});
			if (list.Count == 0)
			{
				yield break;
			}
			Manifest manifest = new Manifest
			{
				schema = 1,
				tiers = list.Select((SkinRecord r) => new Tier
				{
					tier = r.tier,
					name = r.name,
					folder = r.AssetRoot
				}).ToArray()
			};
			GameObject val = BodyCatalog.FindBodyPrefab("LoaderBody");
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("LoaderBody missing");
			}
			model = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
			SurvivorDef val2 = SurvivorCatalog.FindSurvivorDefFromBody(val);
			if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.displayPrefab))
			{
				throw new InvalidOperationException("Loader display missing");
			}
			display = ((Component)val2.displayPrefab.GetComponentInChildren<CharacterModel>(true)).gameObject;
			ModelSkinController ctrl = model.GetComponent<ModelSkinController>();
			if (!Object.op_Implicit((Object)(object)ctrl) || ctrl.skins.Length == 0)
			{
				throw new InvalidOperationException("Loader skins missing");
			}
			SkinDef stock = ctrl.skins[0];
			SkinDefParams bp = stock.skinDefParams;
			if (!Object.op_Implicit((Object)(object)bp))
			{
				IEnumerator load = Load<SkinDefParams>(((AssetReference)stock.skinDefParamsAddress).RuntimeKey, (Action<SkinDefParams>)delegate(SkinDefParams v)
				{
					bp = v;
				});
				while (load.MoveNext())
				{
					yield return null;
				}
			}
			SkinnedMeshRenderer target = model.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, bp).Single((SkinnedMeshRenderer r) => ((Object)r).name == "PilotFemaleMesh");
			RendererInfo val3 = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material native = val3.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)native))
			{
				IEnumerator load = Load<Material>(((AssetReference)val3.defaultMaterialAddress).RuntimeKey, (Action<Material>)delegate(Material v)
				{
					native = v;
				});
				while (load.MoveNext())
				{
					yield return null;
				}
			}
			if (!Object.op_Implicit((Object)(object)native) || !Object.op_Implicit((Object)(object)native.shader))
			{
				throw new InvalidOperationException("Loader native material unavailable");
			}
			List<SkinDef> next = new List<SkinDef>(ctrl.skins);
			List<LoaderDefinition> pending = new List<LoaderDefinition>();
			HashSet<int> hashSet = new HashSet<int>();
			Tier[] tiers = manifest.tiers;
			GameObject[] array;
			foreach (Tier tier in tiers)
			{
				try
				{
					if (tier.tier < 1 || tier.tier > 8 || !hashSet.Add(tier.tier) || Path.GetFileName(tier.folder) != "e" + tier.tier || string.IsNullOrEmpty(tier.name))
					{
						throw new InvalidDataException("Loader tier identity");
					}
					string path = Path.Combine(folder, tier.folder);
					LoaderRig loaderRig = JsonUtility.FromJson<LoaderRig>(File.ReadAllText(Path.Combine(path, "rig.json")));
					ValidateRig(loaderRig, tier.tier);
					array = (GameObject[])(object)new GameObject[2] { model, display };
					for (int num2 = 0; num2 < array.Length; num2++)
					{
						SkinnedMeshRenderer val4 = array[num2].GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null).Single((SkinnedMeshRenderer x) => ((Object)x).name == "PilotFemaleMesh");
						for (int num3 = 0; num3 < 136; num3++)
						{
							if (val4.bones.Length != 136 || !Object.op_Implicit((Object)(object)val4.bones[num3]) || ((Object)val4.bones[num3]).name != loaderRig.bones[num3].name)
							{
								throw new InvalidOperationException("Loader ordered native bone mismatch " + num3);
							}
						}
					}
					LoaderDefinition loaderDefinition = new LoaderDefinition
					{
						Tier = tier.tier,
						Name = tier.name,
						Rig = loaderRig
					};
					loaderDefinition.Body = ReadMesh(Path.Combine(path, "body.meshbin"), loaderRig);
					loaderDefinition.Hook = ReadMesh(Path.Combine(path, "hook.meshbin"), null);
					loaderDefinition.Yank = ReadMesh(Path.Combine(path, "yank.meshbin"), null);
					loaderDefinition.Pylon = ReadMesh(Path.Combine(path, "pylon.meshbin"), null);
					loaderDefinition.Material = new Material(native)
					{
						name = "matEclipseLoaderE" + tier.tier
					};
					Material material = loaderDefinition.Material;
					material.SetTexture("_MainTex", (Texture)(object)Texture(Path.Combine(path, "albedo.png")));
					material.SetColor("_Color", Color.white);
					material.SetFloat("_NormalStrength", 0f);
					material.SetFloat("_Smoothness", (tier.tier == 5) ? 0.65f : 0.12f);
					material.SetFloat("_SpecularStrength", (tier.tier == 5) ? 0.45f : 0.18f);
					material.SetFloat("_SpecularExponent", 8f);
					material.SetFloat("_EmPower", 0f);
					material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
					material.DisableKeyword("FLOWMAP");
					material.SetFloat("_FlowmapOn", 0f);
					material.SetFloat("_FlowEmissionStrength", 0f);
					material.DisableKeyword("LIMBREMOVAL");
					material.SetFloat("_LimbRemovalOn", 0f);
					material.DisableKeyword("FORCE_SPEC");
					material.SetFloat("_ForceSpecOn", 0f);
					Mesh val5 = new Mesh
					{
						name = "EclipseLoaderE" + tier.tier + "EmptyNativeCompanions"
					};
					val5.vertices = Array.Empty<Vector3>();
					val5.triangles = Array.Empty<int>();
					RendererInfo[] array2 = (RendererInfo[])bp.rendererInfos.Clone();
					for (int num4 = 0; num4 < array2.Length; num4++)
					{
						if ((Object)(object)array2[num4].renderer == (Object)(object)target)
						{
							array2[num4].defaultMaterial = material;
							array2[num4].defaultMaterialAddress = new AssetReferenceT<Material>("");
						}
					}
					List<MeshReplacement> list2 = new List<MeshReplacement>();
					SkinnedMeshRenderer[] skinRenderers = model.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, bp);
					foreach (SkinnedMeshRenderer val6 in skinRenderers)
					{
						if ((Object)(object)val6 == (Object)(object)target || ((Object)val6).name == "LoaderMechMesh" || ((Object)val6).name == "PilotFemaleFoldedOverJumpsuit")
						{
							list2.Add(new MeshReplacement
							{
								renderer = (Renderer)(object)val6,
								mesh = (((Object)(object)val6 == (Object)(object)target) ? loaderDefinition.Body : val5),
								meshAddress = new AssetReferenceT<Mesh>("")
							});
						}
					}
					if (list2.Count != 3)
					{
						throw new InvalidOperationException("Unexpected Loader companion set");
					}
					SkinDefParams val7 = ScriptableObject.CreateInstance<SkinDefParams>();
					val7.rendererInfos = array2;
					val7.meshReplacements = list2.ToArray();
					SkinDef skin = ScriptableObject.CreateInstance<SkinDef>();
					((Object)skin).name = loaderRig.skinId;
					skin.nameToken = "ECLIPSE_LOADER_E" + tier.tier;
					LanguageAPI.Add(skin.nameToken, tier.name + " (Playtest)");
					skin.rootObject = model;
					skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { stock };
					skin.skinDefParams = val7;
					skin.unlockableDef = null;
					Texture2D val8 = Texture(Path.Combine(path, "icon.png"));
					skin.icon = Sprite.Create(val8, new Rect(0f, 0f, (float)((Texture)val8).width, (float)((Texture)val8).height), new Vector2(0.5f, 0.5f));
					loaderDefinition.Marker = new SkinDefMarker
					{
						Skin = skin
					};
					if (next.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == ((Object)skin).name))
					{
						throw new InvalidOperationException("Duplicate Loader skin " + ((Object)skin).name);
					}
					pending.Add(loaderDefinition);
					next.Add(skin);
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("RODANIUS_LOADER_SKIN_FAILED tier=" + tier.tier + " " + ex));
				}
			}
			if (pending.Count == 0)
			{
				yield break;
			}
			string[] array3 = new string[3] { "LoaderHook", "LoaderYankHook", "LoaderPylon" };
			foreach (string kind in array3)
			{
				GameObject prefab = null;
				IEnumerator load = Load<GameObject>((object)("RoR2/Base/Loader/" + kind + ".prefab"), (Action<GameObject>)delegate(GameObject p)
				{
					prefab = p;
				});
				while (load.MoveNext())
				{
					yield return null;
				}
				ProjectileController component = prefab.GetComponent<ProjectileController>();
				if (!Object.op_Implicit((Object)(object)component))
				{
					throw new InvalidOperationException("Loader projectile controller missing");
				}
				ProjectileKinds[component.catalogIndex] = kind;
			}
			array = (GameObject[])(object)new GameObject[2] { model, display };
			foreach (GameObject val9 in array)
			{
				(val9.GetComponent<LoaderVisualRig>() ?? val9.AddComponent<LoaderVisualRig>()).Configure(val9.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null).Single((SkinnedMeshRenderer r) => ((Object)r).name == "PilotFemaleMesh"));
			}
			foreach (LoaderDefinition item in pending)
			{
				ByMesh.Add(item.Body, item);
				BySkin.Add(item.Rig.skinId, item);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_LOADER_TIER_READY tier=" + item.Tier + " name=" + item.Name));
			}
			ctrl.skins = next.ToArray();
			registered = true;
			ProjectileController.Start += new hook_Start(ProjectileStart);
			SyncDisplay();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_LOADER_REGISTERED count=" + pending.Count + " version=0.2.0"));
		}

		private void SyncDisplay()
		{
			if (registered && Object.op_Implicit((Object)(object)display) && Object.op_Implicit((Object)(object)model))
			{
				(display.GetComponent<ModelSkinController>() ?? display.AddComponent<ModelSkinController>()).skins = (SkinDef[])model.GetComponent<ModelSkinController>().skins.Clone();
			}
		}

		private void ProjectileStart(orig_Start orig, ProjectileController self)
		{
			orig.Invoke(self);
			if (Object.op_Implicit((Object)(object)self) && ProjectileKinds.ContainsKey(self.catalogIndex))
			{
				(((Component)self).GetComponent<LoaderProjectileVisual>() ?? ((Component)self).gameObject.AddComponent<LoaderProjectileVisual>()).Configure(self, ProjectileKinds[self.catalogIndex]);
			}
		}

		private static Texture2D Texture(string path)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0033: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false)
			{
				anisoLevel = 4,
				filterMode = (FilterMode)2
			};
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path), false))
			{
				throw new InvalidDataException("Loader image decode failed");
			}
			return val;
		}

		private static void ValidateRig(LoaderRig r, int tier)
		{
			if (r == null || r.schema != 1 || r.tier != tier || r.skinId != "EclipseLoaderE" + tier || r.bones == null || r.bones.Length != 136)
			{
				throw new InvalidDataException("Loader rig identity");
			}
			HashSet<string> hashSet = new HashSet<string>();
			for (int i = 0; i < r.bones.Length; i++)
			{
				LoaderBone loaderBone = r.bones[i];
				if (loaderBone == null || !hashSet.Add(loaderBone.name) || loaderBone.parent >= i || loaderBone.parent < -1)
				{
					throw new InvalidDataException("Loader rig hierarchy");
				}
				float[][] array = new float[4][] { loaderBone.position, loaderBone.scale, loaderBone.nativePosition, loaderBone.nativeScale };
				foreach (float[] array2 in array)
				{
					if (array2 == null || array2.Length != 3 || array2.Any((float x) => float.IsNaN(x) || float.IsInfinity(x)))
					{
						throw new InvalidDataException("Loader rig vector");
					}
				}
				array = new float[2][] { loaderBone.rotation, loaderBone.nativeRotation };
				foreach (float[] array3 in array)
				{
					if (array3 == null || array3.Length != 4 || array3.Any((float x) => float.IsNaN(x) || float.IsInfinity(x)) || (double)Math.Abs(array3.Sum((float x) => x * x) - 1f) > 0.005)
					{
						throw new InvalidDataException("Loader rig quaternion");
					}
				}
				if (loaderBone.bindpose == null || loaderBone.bindpose.Length != 16 || loaderBone.bindpose.Any((float x) => float.IsNaN(x) || float.IsInfinity(x)) || loaderBone.nativeScale.Any((float x) => (double)Math.Abs(x) < 1E-06))
				{
					throw new InvalidDataException("Loader rig bind pose");
				}
			}
		}

		private static Mesh ReadMesh(string path, LoaderRig rig)
		{
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: 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)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0398: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Expected O, but got Unknown
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			using BinaryReader binaryReader = new BinaryReader(File.OpenRead(path));
			if (new string(binaryReader.ReadChars(4)) != "PWE1")
			{
				throw new InvalidDataException("Loader mesh signature");
			}
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			int num3 = binaryReader.ReadInt32();
			if (num < 3 || num > 200000 || num2 < 3 || num2 > 1200000 || num2 % 3 != 0 || num3 != ((rig == null) ? 1 : 136))
			{
				throw new InvalidDataException("Loader mesh dimensions");
			}
			for (int i = 0; i < num3; i++)
			{
				int num4 = binaryReader.ReadInt32();
				if (num4 < 1 || num4 > 128)
				{
					throw new InvalidDataException("Loader bone length");
				}
				if (Encoding.UTF8.GetString(binaryReader.ReadBytes(num4)) != ((rig == null) ? "root" : rig.bones[i].name))
				{
					throw new InvalidDataException("Loader mesh bone slot");
				}
			}
			if (binaryReader.BaseStream.Length - binaryReader.BaseStream.Position != 64L * (long)num + 4L * (long)num2)
			{
				throw new InvalidDataException("Loader mesh length");
			}
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num];
			BoneWeight[] array4 = (BoneWeight[])(object)new BoneWeight[num];
			for (int j = 0; j < num; j++)
			{
				array[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array3[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
				int[] array5 = new int[4];
				float[] array6 = new float[4];
				for (int k = 0; k < 4; k++)
				{
					array5[k] = binaryReader.ReadInt32();
					if (array5[k] < 0 || array5[k] >= num3)
					{
						throw new InvalidDataException("Loader weight bone");
					}
				}
				for (int l = 0; l < 4; l++)
				{
					array6[l] = binaryReader.ReadSingle();
				}
				if (!Finite(array[j]) || !Finite(array2[j]) || float.IsNaN(array3[j].x + array3[j].y) || float.IsInfinity(array3[j].x + array3[j].y) || (double)Math.Abs(((Vector3)(ref array2[j])).magnitude - 1f) > 0.002 || array6.Any((float x) => float.IsNaN(x) || float.IsInfinity(x) || x < 0f) || (double)Math.Abs(array6.Sum() - 1f) > 0.002)
				{
					throw new InvalidDataException("Loader vertex attributes");
				}
				int num5 = j;
				BoneWeight val = default(BoneWeight);
				((BoneWeight)(ref val)).boneIndex0 = array5[0];
				((BoneWeight)(ref val)).boneIndex1 = array5[1];
				((BoneWeight)(ref val)).boneIndex2 = array5[2];
				((BoneWeight)(ref val)).boneIndex3 = array5[3];
				((BoneWeight)(ref val)).weight0 = array6[0];
				((BoneWeight)(ref val)).weight1 = array6[1];
				((BoneWeight)(ref val)).weight2 = array6[2];
				((BoneWeight)(ref val)).weight3 = array6[3];
				array4[num5] = val;
			}
			int[] array7 = new int[num2];
			for (int num6 = 0; num6 < num2; num6++)
			{
				array7[num6] = binaryReader.ReadInt32();
				if (array7[num6] < 0 || array7[num6] >= num)
				{
					throw new InvalidDataException("Loader mesh index");
				}
			}
			Mesh val2 = new Mesh
			{
				name = Path.GetFileName(path),
				indexFormat = (IndexFormat)1
			};
			val2.vertices = array;
			val2.normals = array2;
			val2.uv = array3;
			val2.triangles = array7;
			if (rig != null)
			{
				val2.boneWeights = array4;
				Matrix4x4[] array8 = (Matrix4x4[])(object)new Matrix4x4[num3];
				for (int num7 = 0; num7 < num3; num7++)
				{
					for (int num8 = 0; num8 < 4; num8++)
					{
						for (int num9 = 0; num9 < 4; num9++)
						{
							((Matrix4x4)(ref array8[num7]))[num8, num9] = rig.bones[num7].bindpose[num8 * 4 + num9];
						}
					}
				}
				val2.bindposes = array8;
			}
			val2.RecalculateBounds();
			val2.RecalculateTangents();
			return val2;
		}

		private static bool Finite(Vector3 v)
		{
			//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			if (!float.IsNaN(v.x + v.y + v.z))
			{
				return !float.IsInfinity(v.x + v.y + v.z);
			}
			return false;
		}

		private void OnDestroy()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplay));
			MainMenuController.OnMainMenuInitialised -= SyncDisplay;
			ProjectileController.Start -= new hook_Start(ProjectileStart);
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
	internal sealed class LoaderGorillaGait
	{
		private readonly Transform space;

		private readonly Transform[] bones;

		private readonly Transform[] native;

		private readonly LoaderRig rig;

		private readonly CharacterBody body;

		private readonly Animator animator;

		private readonly int[] upper = new int[2];

		private readonly int[] lower = new int[2];

		private readonly int[] hand = new int[2];

		private readonly Vector3[] restHand = (Vector3[])(object)new Vector3[2];

		private readonly Quaternion[] restHandRotation = (Quaternion[])(object)new Quaternion[2];

		private readonly EntityStateMachine[] machines = (EntityStateMachine[])(object)new EntityStateMachine[4];

		private readonly int[] layers = new int[7];

		private float weight;

		private static readonly string[] MachineNames = new string[4] { "Body", "Weapon", "Hook", "Pylon" };

		private static readonly string[] LayerNames = new string[7] { "Body", "Grapple", "Gesture, Additive", "Gesture, Override", "FullBody, Override", "Flinch", "Impact" };

		public LoaderGorillaGait(Transform model, Transform rendererSpace, Transform[] visual, Transform[] source, LoaderRig definition)
		{
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			space = rendererSpace;
			bones = visual;
			native = source;
			rig = definition;
			body = ((Component)model).GetComponentInParent<CharacterBody>();
			animator = ((Component)model).GetComponent<Animator>();
			for (int i = 0; i < 2; i++)
			{
				string text = ((i == 0) ? "l" : "r");
				upper[i] = Find("mech.upper_arm." + text);
				lower[i] = Find("mech.lower_arm." + text);
				hand[i] = Find("mech.hand." + text);
				LoaderBone loaderBone = rig.bones[hand[i]];
				Matrix4x4 val = default(Matrix4x4);
				for (int j = 0; j < 16; j++)
				{
					((Matrix4x4)(ref val))[j / 4, j % 4] = loaderBone.bindpose[j];
				}
				val = ((Matrix4x4)(ref val)).inverse;
				restHand[i] = Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(3));
				restHandRotation[i] = ((Matrix4x4)(ref val)).rotation;
			}
			if (Object.op_Implicit((Object)(object)body))
			{
				for (int k = 0; k < 4; k++)
				{
					machines[k] = EntityStateMachine.FindByCustomName(((Component)body).gameObject, MachineNames[k]);
				}
			}
			for (int l = 0; l < layers.Length; l++)
			{
				layers[l] = (Object.op_Implicit((Object)(object)animator) ? animator.GetLayerIndex(LayerNames[l]) : (-1));
			}
		}

		private int Find(string name)
		{
			for (int i = 0; i < rig.bones.Length; i++)
			{
				if (rig.bones[i].name == name)
				{
					return i;
				}
			}
			throw new InvalidOperationException("Missing gorilla bone " + name);
		}

		private bool AllowedState(AnimatorStateInfo state, int layer)
		{
			if (layer == 0)
			{
				if (!((AnimatorStateInfo)(ref state)).IsName("Body.Idle") && !((AnimatorStateInfo)(ref state)).IsName("Body.IdleIn"))
				{
					return ((AnimatorStateInfo)(ref state)).IsName("Body.Run");
				}
				return true;
			}
			if (!((AnimatorStateInfo)(ref state)).IsName(LayerNames[layer] + ".Empty"))
			{
				return ((AnimatorStateInfo)(ref state)).IsName(LayerNames[layer] + ".BufferEmpty");
			}
			return true;
		}

		private bool GroundedGate()
		{
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive || !Object.op_Implicit((Object)(object)body.characterMotor) || !((Behaviour)body.characterMotor).isActiveAndEnabled || !body.characterMotor.isGrounded || body.characterMotor.isFlying || !Object.op_Implicit((Object)(object)animator))
			{
				return false;
			}
			for (int i = 0; i < 4; i++)
			{
				if (!Object.op_Implicit((Object)(object)machines[i]) || !machines[i].IsInMainState() || machines[i].HasPendingState())
				{
					return false;
				}
			}
			if (!(machines[0].state is GenericCharacterMain))
			{
				return false;
			}
			for (int j = 1; j < 4; j++)
			{
				if (((object)machines[j].state).GetType() != typeof(Idle))
				{
					return false;
				}
			}
			if (body.hasEffectiveAuthority && Object.op_Implicit((Object)(object)body.inputBank))
			{
				InputBankTest inputBank = body.inputBank;
				if (inputBank.jump.down || ((ButtonState)(ref inputBank.jump)).justPressed || inputBank.skill1.down || ((ButtonState)(ref inputBank.skill1)).justPressed || inputBank.skill2.down || ((ButtonState)(ref inputBank.skill2)).justPressed || inputBank.skill3.down || ((ButtonState)(ref inputBank.skill3)).justPressed || inputBank.skill4.down || ((ButtonState)(ref inputBank.skill4)).justPressed || inputBank.activateEquipment.down || ((ButtonState)(ref inputBank.activateEquipment)).justPressed)
				{
					return false;
				}
			}
			for (int k = 0; k < layers.Length; k++)
			{
				if (layers[k] < 0 || animator.IsInTransition(layers[k]) || !AllowedState(animator.GetCurrentAnimatorStateInfo(layers[k]), k))
				{
					return false;
				}
			}
			return true;
		}

		public void Apply()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body))
			{
				for (int i = 0; i < 2; i++)
				{
					Solve(i, space.TransformPoint(restHand[i]), space.rotation * restHandRotation[i]);
				}
				return;
			}
			if (!Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive)
			{
				weight = 0f;
				return;
			}
			bool flag = GroundedGate();
			weight = (flag ? Mathf.MoveTowards(weight, 1f, Time.deltaTime * 6f) : 0f);
			float num = (Object.op_Implicit((Object)(object)body.characterMotor) ? Mathf.Clamp01(((Vector3)(ref body.characterMotor.velocity)).magnitude / Mathf.Max(1f, body.moveSpeed)) : 0f);
			float num2;
			if (!flag)
			{
				num2 = 0f;
			}
			else
			{
				AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(layers[0]);
				num2 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime;
			}
			float num3 = num2;
			for (int j = 0; j < 2; j++)
			{
				Quaternion rotation = bones[hand[j]].rotation;
				Vector3 position = native[hand[j]].position;
				if (weight > 0f)
				{
					float num4 = Mathf.Repeat(num3 + (float)j * 0.5f, 1f);
					float num5;
					float num6;
					if (num4 < 0.6f)
					{
						num5 = Mathf.Lerp(-0.14f, 0.14f, num4 / 0.6f);
						num6 = 0f;
					}
					else
					{
						float num7 = (num4 - 0.6f) / 0.4f;
						num5 = Mathf.Lerp(0.14f, -0.14f, num7);
						num6 = Mathf.Sin(num7 * (float)Math.PI) * 0.12f;
					}
					Vector3 val = space.TransformPoint(restHand[j] + new Vector3(0f, num5 * num, num6 * num));
					Solve(j, Vector3.Lerp(position, val, weight), Quaternion.Slerp(rotation, space.rotation * restHandRotation[j], weight), planted: true);
				}
				else
				{
					Solve(j, position, rotation);
				}
			}
		}

		private void Solve(int side, Vector3 target, Quaternion orientation, bool planted = false)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: 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_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: 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)
			//IL_023c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			Transform val = bones[upper[side]];
			Transform val2 = bones[lower[side]];
			Transform val3 = bones[hand[side]];
			Vector3 position = val.position;
			Vector3 val4 = val2.position - position;
			Vector3 val5 = val3.position - val2.position;
			Vector3 val6 = target - position;
			float magnitude = ((Vector3)(ref val4)).magnitude;
			float magnitude2 = ((Vector3)(ref val5)).magnitude;
			float magnitude3 = ((Vector3)(ref val6)).magnitude;
			if (!(magnitude < 0.001f) && !(magnitude2 < 0.001f) && !(magnitude3 < 0.001f))
			{
				if (planted && magnitude3 > magnitude + magnitude2 - 0.0005f)
				{
					float num = Mathf.Min(1.18f, (magnitude3 + 0.001f) / (magnitude + magnitude2));
					val2.position = position + val4 * num;
					val3.position = val2.position + val5 * num;
					val4 = val2.position - position;
					val5 = val3.position - val2.position;
					magnitude = ((Vector3)(ref val4)).magnitude;
					magnitude2 = ((Vector3)(ref val5)).magnitude;
				}
				float num2 = Mathf.Clamp(magnitude3, Mathf.Abs(magnitude - magnitude2) + 0.0005f, magnitude + magnitude2 - 0.0005f);
				Vector3 val7 = val6 / magnitude3;
				Vector3 val8 = Vector3.ProjectOnPlane(space.TransformDirection(new Vector3((side == 0) ? (-0.5f) : 0.5f, 0.4f, 0.1f)), val7);
				Vector3 normalized = ((Vector3)(ref val8)).normalized;
				if (!(((Vector3)(ref normalized)).sqrMagnitude < 0.5f))
				{
					float num3 = (magnitude * magnitude + num2 * num2 - magnitude2 * magnitude2) / (2f * num2);
					float num4 = Mathf.Sqrt(Mathf.Max(0f, magnitude * magnitude - num3 * num3));
					Vector3 val9 = position + val7 * num3 + normalized * num4;
					val.rotation = Quaternion.FromToRotation(val4, val9 - position) * val.rotation;
					val2.rotation = Quaternion.FromToRotation(val3.position - val2.position, position + val7 * num2 - val2.position) * val2.rotation;
					val3.rotation = orientation;
				}
			}
		}
	}
	[DefaultExecutionOrder(32000)]
	public sealed class LoaderProjectileVisual : MonoBehaviour
	{
		private ProjectileController projectile;

		private strin

BepInEx/plugins/RodaniusSkinRuntime/Eclipse.RailgunnerSkins.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using EntityStates;
using EntityStates.Railgunner.Weapon;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
using Rodanius.Standalone;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Eclipse.RailgunnerSkins
{
	[BepInPlugin("eclipseplaytest.railgunner.collection", "Eclipse Railgunner Skins (Private Playtest)", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class RailgunnerCollection : BaseUnityPlugin
	{
		[Serializable]
		public sealed class Manifest
		{
			public int schema;

			public Tier[] tiers;
		}

		[Serializable]
		public sealed class Tier
		{
			public int tier;

			public string name;

			public string folder;
		}

		[Serializable]
		public sealed class Bone
		{
			public string name;

			public int parent;

			public float[] bindpose;
		}

		[Serializable]
		public sealed class Presentation
		{
			public int schema;

			public float[] sniperMuzzleBodyLocal;
		}

		[Serializable]
		public sealed class Rig
		{
			public int schema;

			public int tier;

			public string skinId;

			public Bone[] bones;
		}

		public const string Guid = "eclipseplaytest.railgunner.collection";

		public const string Version = "0.2.0";

		public static readonly HashSet<Mesh> AuthoredMeshes = new HashSet<Mesh>();

		public static readonly Dictionary<Mesh, Vector3> MuzzlePositions = new Dictionary<Mesh, Vector3>();

		public static bool PresentationEnabled;

		private bool warnedMuzzle;

		private bool muzzleSubscribed;

		private static RailgunnerCollection instance;

		private string folder;

		private float deadline;

		private GameObject model;

		private GameObject display;

		private bool registered;

		private readonly List<AsyncOperationHandle> handles = new List<AsyncOperationHandle>();

		private static readonly string[] Replaced = new string[4] { "mdlRailGunnerBase", "mdlRailGunnerMetal", "mdlRailgunProto", "mdlRailgunBackpackMesh" };

		private void Awake()
		{
			instance = this;
			folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(RailgunnerCollection));
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplay));
			MainMenuController.OnMainMenuInitialised += SyncDisplay;
		}

		[SystemInitializer(new Type[]
		{
			typeof(BodyCatalog),
			typeof(SurvivorCatalog)
		})]
		private static IEnumerator Initialize()
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				yield break;
			}
			instance.deadline = Time.realtimeSinceStartup + 90f;
			IEnumerator e = instance.Register();
			try
			{
				while (true)
				{
					bool flag;
					try
					{
						flag = e.MoveNext();
					}
					catch (Exception ex)
					{
						((BaseUnityPlugin)instance).Logger.LogError((object)("ECLIPSE_RAILGUNNER_REGISTRATION_FAILED " + ex));
						break;
					}
					if (flag)
					{
						yield return e.Current;
						continue;
					}
					break;
				}
			}
			finally
			{
				IDisposable disposable = e as IDisposable;
				if (disposable != null)
				{
					disposable.Dispose();
				}
			}
		}

		private IEnumerator Load<T>(object key, Action<T> set) where T : Object
		{
			AsyncOperationHandle<T> op = Addressables.LoadAssetAsync<T>(key);
			handles.Add(AsyncOperationHandle<T>.op_Implicit(op));
			while (!op.IsDone)
			{
				if (Time.realtimeSinceStartup > deadline)
				{
					throw new TimeoutException("Railgunner loading exceeded deadline");
				}
				yield return null;
			}
			if (!Object.op_Implicit((Object)(object)op.Result))
			{
				throw new InvalidDataException("Missing native asset " + key);
			}
			set(op.Result);
		}

		private static SkinnedMeshRenderer Renderer(GameObject root, string name)
		{
			Transform obj = root.transform.Find(name);
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("Required Railgunner renderer path missing: " + name);
			}
			SkinnedMeshRenderer component = ((Component)obj).GetComponent<SkinnedMeshRenderer>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				throw new InvalidOperationException("Expected skinned renderer: " + name);
			}
			return component;
		}

		private IEnumerator Register()
		{
			List<SkinRecord> list = SkinDiscovery.Load("railgunner", delegate(string m)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)m);
			});
			if (list.Count == 0)
			{
				yield break;
			}
			Manifest manifest = new Manifest
			{
				schema = 1,
				tiers = list.Select((SkinRecord r) => new Tier
				{
					tier = r.tier,
					name = r.name,
					folder = r.AssetRoot
				}).ToArray()
			};
			GameObject val = BodyCatalog.FindBodyPrefab("RailgunnerBody");
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("RailgunnerBody missing");
			}
			model = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
			SurvivorDef val2 = SurvivorCatalog.FindSurvivorDefFromBody(val);
			if (!Object.op_Implicit((Object)(object)val2) || !Object.op_Implicit((Object)(object)val2.displayPrefab))
			{
				throw new InvalidOperationException("Railgunner display missing");
			}
			display = ((Component)val2.displayPrefab.GetComponentInChildren<CharacterModel>(true)).gameObject;
			ModelSkinController ctrl = model.GetComponent<ModelSkinController>();
			if (!Object.op_Implicit((Object)(object)ctrl) || ctrl.skins == null || ctrl.skins.Length == 0)
			{
				throw new InvalidOperationException("Railgunner stock skins missing");
			}
			SkinDef stock = ctrl.skins[0];
			SkinDefParams bp = stock.skinDefParams;
			if (!Object.op_Implicit((Object)(object)bp))
			{
				IEnumerator load = Load<SkinDefParams>(((AssetReference)stock.skinDefParamsAddress).RuntimeKey, (Action<SkinDefParams>)delegate(SkinDefParams v)
				{
					bp = v;
				});
				while (load.MoveNext())
				{
					yield return null;
				}
			}
			if (!Object.op_Implicit((Object)(object)bp) || bp.rendererInfos == null)
			{
				throw new InvalidDataException("Default skin parameters unavailable");
			}
			SkinnedMeshRenderer target = Renderer(model, "mdlRailGunnerBase");
			RendererInfo val3 = bp.rendererInfos.Single((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material native = val3.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)native))
			{
				IEnumerator load = Load<Material>(((AssetReference)val3.defaultMaterialAddress).RuntimeKey, (Action<Material>)delegate(Material v)
				{
					native = v;
				});
				while (load.MoveNext())
				{
					yield return null;
				}
			}
			if (!Object.op_Implicit((Object)(object)native) || !Object.op_Implicit((Object)(object)native.shader))
			{
				throw new InvalidOperationException("Native body shader unavailable");
			}
			for (int num = 0; num < bp.rendererInfos.Length; num++)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_RAILGUNNER_NATIVE_RENDERER index=" + num + " path=" + (Object.op_Implicit((Object)(object)bp.rendererInfos[num].renderer) ? ((Object)bp.rendererInfos[num].renderer).name : "null")));
			}
			GameObject[] array = (GameObject[])(object)new GameObject[2] { model, display };
			foreach (GameObject root in array)
			{
				string[] replaced = Replaced;
				foreach (string name in replaced)
				{
					Renderer(root, name);
				}
				Renderer(root, "mdlRailGunBackpackScreen");
			}
			List<SkinDef> list2 = new List<SkinDef>(ctrl.skins);
			List<Mesh> list3 = new List<Mesh>();
			HashSet<int> hashSet = new HashSet<int>();
			Tier[] tiers = manifest.tiers;
			Vector3 val4 = default(Vector3);
			foreach (Tier tier in tiers)
			{
				try
				{
					if (tier.tier < 1 || tier.tier > 8 || !hashSet.Add(tier.tier) || Path.GetFileName(tier.folder) != "e" + tier.tier || string.IsNullOrEmpty(tier.name))
					{
						throw new InvalidDataException("Tier identity");
					}
					string path = Path.Combine(folder, tier.folder);
					Rig rig = JsonUtility.FromJson<Rig>(File.ReadAllText(Path.Combine(path, "rig.json")));
					ValidateRig(rig, tier.tier);
					array = (GameObject[])(object)new GameObject[2] { model, display };
					for (int num3 = 0; num3 < array.Length; num3++)
					{
						ValidateBinding(Renderer(array[num3], "mdlRailGunnerBase"), rig);
					}
					Mesh mesh = ReadMesh(Path.Combine(path, "body.meshbin"), rig);
					((Object)mesh).name = rig.skinId + "_AuthoredBodyAndRifle";
					Presentation presentation = JsonUtility.FromJson<Presentation>(File.ReadAllText(Path.Combine(path, "presentation.json")));
					if (presentation == null || presentation.schema != 1 || presentation.sniperMuzzleBodyLocal == null || presentation.sniperMuzzleBodyLocal.Length != 3 || presentation.sniperMuzzleBodyLocal.Any((float x) => float.IsNaN(x) || float.IsInfinity(x)))
					{
						throw new InvalidDataException("Cosmetic muzzle presentation");
					}
					((Vector3)(ref val4))..ctor(presentation.sniperMuzzleBodyLocal[0], presentation.sniperMuzzleBodyLocal[1], presentation.sniperMuzzleBodyLocal[2]);
					if (((Vector3)(ref val4)).magnitude > 4f)
					{
						throw new InvalidDataException("Cosmetic muzzle bounds");
					}
					MuzzlePositions.Add(mesh, ((Matrix4x4)(ref mesh.bindposes[104])).MultiplyPoint3x4(val4));
					Material val5 = new Material(native)
					{
						name = "matEclipseRailgunnerE" + tier.tier
					};
					val5.SetTexture("_MainTex", (Texture)(object)Texture(Path.Combine(path, "albedo.png")));
					val5.SetColor("_Color", Color.white);
					val5.SetFloat("_NormalStrength", 0f);
					val5.SetFloat("_Smoothness", 0.16f);
					val5.SetFloat("_SpecularStrength", 0.2f);
					val5.SetFloat("_SpecularExponent", 8f);
					val5.SetFloat("_EmPower", 0f);
					val5.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
					val5.DisableKeyword("FLOWMAP");
					val5.SetFloat("_FlowmapOn", 0f);
					val5.SetFloat("_FlowEmissionStrength", 0f);
					val5.DisableKeyword("LIMBREMOVAL");
					val5.SetFloat("_LimbRemovalOn", 0f);
					val5.DisableKeyword("FORCE_SPEC");
					val5.SetFloat("_ForceSpecOn", 0f);
					Mesh empty = new Mesh
					{
						name = rig.skinId + "_EmptyReplacedParts"
					};
					empty.vertices = Array.Empty<Vector3>();
					empty.triangles = Array.Empty<int>();
					RendererInfo[] array2 = (RendererInfo[])bp.rendererInfos.Clone();
					for (int num4 = 0; num4 < array2.Length; num4++)
					{
						if ((Object)(object)array2[num4].renderer == (Object)(object)target)
						{
							array2[num4].defaultMaterial = val5;
							array2[num4].defaultMaterialAddress = new AssetReferenceT<Material>("");
						}
					}
					MeshReplacement[] meshReplacements = ((IEnumerable<string>)Replaced).Select((Func<string, MeshReplacement>)((string text) => new MeshReplacement
					{
						renderer = (Renderer)(object)Renderer(model, text),
						mesh = ((text == "mdlRailGunnerBase") ? mesh : empty),
						meshAddress = new AssetReferenceT<Mesh>("")
					})).ToArray();
					SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
					((Object)val6).name = rig.skinId + "_Params";
					val6.rendererInfos = array2;
					val6.meshReplacements = meshReplacements;
					SkinDef skin = ScriptableObject.CreateInstance<SkinDef>();
					((Object)skin).name = rig.skinId;
					skin.nameToken = "ECLIPSE_RAILGUNNER_E" + tier.tier;
					LanguageAPI.Add(skin.nameToken, tier.name + " (Playtest)");
					skin.rootObject = model;
					skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { stock };
					skin.skinDefParams = val6;
					skin.unlockableDef = null;
					Texture2D val7 = Texture(Path.Combine(path, "icon.png"));
					skin.icon = Sprite.Create(val7, new Rect(0f, 0f, (float)((Texture)val7).width, (float)((Texture)val7).height), new Vector2(0.5f, 0.5f));
					if (list2.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == ((Object)skin).name))
					{
						throw new InvalidOperationException("Duplicate skin " + ((Object)skin).name);
					}
					list2.Add(skin);
					list3.Add(mesh);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_RAILGUNNER_TIER_READY tier=" + tier.tier + " name=" + tier.name + " vertices=" + mesh.vertexCount));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("RODANIUS_RAILGUNNER_SKIN_FAILED tier=" + tier.tier + " " + ex));
				}
			}
			if (list3.Count == 0)
			{
				yield break;
			}
			array = (GameObject[])(object)new GameObject[2] { model, display };
			foreach (GameObject val8 in array)
			{
				(val8.GetComponent<RailgunnerBounds>() ?? val8.AddComponent<RailgunnerBounds>()).Configure(Renderer(val8, "mdlRailGunnerBase"));
				(val8.GetComponent<RailgunnerMuzzle>() ?? val8.AddComponent<RailgunnerMuzzle>()).Configure(Renderer(val8, "mdlRailGunnerBase"), val8.GetComponent<ChildLocator>());
			}
			foreach (Mesh item in list3)
			{
				AuthoredMeshes.Add(item);
			}
			ctrl.skins = list2.ToArray();
			registered = true;
			OnEnable();
			SyncDisplay();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_RAILGUNNER_REGISTERED count=" + list3.Count + " version=0.2.0"));
		}

		private void OnEnable()
		{
			if (registered)
			{
				PresentationEnabled = true;
				if (!muzzleSubscribed)
				{
					BaseFireSnipe.onFireSnipe += AdaptSniperMuzzle;
					muzzleSubscribed = true;
				}
			}
		}

		private void OnDisable()
		{
			PresentationEnabled = false;
			if (muzzleSubscribed)
			{
				BaseFireSnipe.onFireSnipe -= AdaptSniperMuzzle;
				muzzleSubscribed = false;
			}
			RailgunnerMuzzle[] array = Object.FindObjectsOfType<RailgunnerMuzzle>();
			for (int i = 0; i < array.Length; i++)
			{
				array[i].Release();
			}
			RailgunnerBounds[] array2 = Object.FindObjectsOfType<RailgunnerBounds>();
			for (int i = 0; i < array2.Length; i++)
			{
				array2[i].Release();
			}
		}

		internal static void ReportMuzzleValidation(string reason)
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				((BaseUnityPlugin)instance).Logger.LogWarning((object)("ECLIPSE_RAILGUNNER_MUZZLE_VALIDATION_SKIPPED " + reason));
			}
		}

		private void AdaptSniperMuzzle(BaseFireSnipe state)
		{
			try
			{
				Type type = ((object)state).GetType();
				if ((type != typeof(FireSnipeHeavy) && type != typeof(FireSnipeLight) && type != typeof(FireSnipeSuper) && type != typeof(FireSnipeCryo)) || (((GenericBulletBaseState)state).muzzleName != "MuzzleRight" && ((GenericBulletBaseState)state).muzzleName != "MuzzleSniper") || !Object.op_Implicit((Object)(object)((EntityState)state).outer))
				{
					return;
				}
				ModelLocator component = ((Component)((EntityState)state).outer).GetComponent<ModelLocator>();
				if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.modelTransform))
				{
					RailgunnerMuzzle component2 = ((Component)component.modelTransform).GetComponent<RailgunnerMuzzle>();
					if (Object.op_Implicit((Object)(object)component2) && ((Behaviour)component2).isActiveAndEnabled && component2.Ensure())
					{
						component2.Remember(state);
						((GenericBulletBaseState)state).muzzleName = "MuzzleSniper";
					}
				}
			}
			catch (Exception ex)
			{
				if (!warnedMuzzle)
				{
					warnedMuzzle = true;
					((BaseUnityPlugin)this).Logger.LogWarning((object)("ECLIPSE_RAILGUNNER_COSMETIC_MUZZLE_SKIPPED " + ex.Message));
				}
			}
		}

		private void SyncDisplay()
		{
			if (registered && Object.op_Implicit((Object)(object)display) && Object.op_Implicit((Object)(object)model))
			{
				(display.GetComponent<ModelSkinController>() ?? display.AddComponent<ModelSkinController>()).skins = (SkinDef[])model.GetComponent<ModelSkinController>().skins.Clone();
			}
		}

		private static Texture2D Texture(string path)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			//IL_0033: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false)
			{
				anisoLevel = 4,
				filterMode = (FilterMode)2
			};
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path), false))
			{
				throw new InvalidDataException("Image decode failed");
			}
			return val;
		}

		private static void ValidateRig(Rig r, int tier)
		{
			if (r == null || r.schema != 1 || r.tier != tier || r.skinId != "EclipseRailgunnerE" + tier || r.bones == null || r.bones.Length != 154)
			{
				throw new InvalidDataException("Rig identity");
			}
			HashSet<string> hashSet = new HashSet<string>();
			for (int i = 0; i < r.bones.Length; i++)
			{
				Bone bone = r.bones[i];
				if (bone == null || string.IsNullOrEmpty(bone.name) || !hashSet.Add(bone.name) || bone.parent >= i || bone.parent < -1 || bone.bindpose == null || bone.bindpose.Length != 16 || bone.bindpose.Any((float x) => float.IsNaN(x) || float.IsInfinity(x)))
				{
					throw new InvalidDataException("Rig hierarchy/bindpose");
				}
			}
		}

		private static void ValidateBinding(SkinnedMeshRenderer r, Rig rig)
		{
			if (r.bones.Length != 154)
			{
				throw new InvalidOperationException("Railgunner native bone count changed");
			}
			for (int i = 0; i < 154; i++)
			{
				Transform val = r.bones[i];
				if (!Object.op_Implicit((Object)(object)val) || ((Object)val).name != rig.bones[i].name)
				{
					throw new InvalidOperationException("Railgunner ordered bone mismatch " + i);
				}
				int parent = rig.bones[i].parent;
				if (parent >= 0 && (Object)(object)val.parent != (Object)(object)r.bones[parent])
				{
					throw new InvalidOperationException("Railgunner native ancestry mismatch " + i);
				}
			}
		}

		private static Mesh ReadMesh(string path, Rig rig)
		{
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a2: Expected O, but got Unknown
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			using BinaryReader binaryReader = new BinaryReader(File.OpenRead(path));
			if (new string(binaryReader.ReadChars(4)) != "PWE1")
			{
				throw new InvalidDataException("Mesh signature");
			}
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			int num3 = binaryReader.ReadInt32();
			if (num < 3 || num > 200000 || num2 < 3 || num2 > 1200000 || num2 % 3 != 0 || num3 != 154)
			{
				throw new InvalidDataException("Mesh dimensions");
			}
			for (int i = 0; i < num3; i++)
			{
				int num4 = binaryReader.ReadInt32();
				if (num4 < 1 || num4 > 128)
				{
					throw new InvalidDataException("Bone length");
				}
				if (Encoding.UTF8.GetString(binaryReader.ReadBytes(num4)) != rig.bones[i].name)
				{
					throw new InvalidDataException("Mesh bone slot");
				}
			}
			if (binaryReader.BaseStream.Length - binaryReader.BaseStream.Position != 64L * (long)num + 4L * (long)num2)
			{
				throw new InvalidDataException("Mesh length");
			}
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num];
			BoneWeight[] array4 = (BoneWeight[])(object)new BoneWeight[num];
			for (int j = 0; j < num; j++)
			{
				array[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array3[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
				int[] array5 = new int[4];
				float[] array6 = new float[4];
				for (int k = 0; k < 4; k++)
				{
					array5[k] = binaryReader.ReadInt32();
					if (array5[k] < 0 || array5[k] >= num3)
					{
						throw new InvalidDataException("Weight bone");
					}
				}
				for (int l = 0; l < 4; l++)
				{
					array6[l] = binaryReader.ReadSingle();
				}
				if (!Finite(array[j]) || !Finite(array2[j]) || float.IsNaN(array3[j].x + array3[j].y) || float.IsInfinity(array3[j].x + array3[j].y) || (double)Math.Abs(((Vector3)(ref array2[j])).magnitude - 1f) > 0.002 || array6.Any((float x) => float.IsNaN(x) || float.IsInfinity(x) || x < 0f) || (double)Math.Abs(array6.Sum() - 1f) > 0.002)
				{
					throw new InvalidDataException("Vertex attributes");
				}
				int num5 = j;
				BoneWeight val = default(BoneWeight);
				((BoneWeight)(ref val)).boneIndex0 = array5[0];
				((BoneWeight)(ref val)).boneIndex1 = array5[1];
				((BoneWeight)(ref val)).boneIndex2 = array5[2];
				((BoneWeight)(ref val)).boneIndex3 = array5[3];
				((BoneWeight)(ref val)).weight0 = array6[0];
				((BoneWeight)(ref val)).weight1 = array6[1];
				((BoneWeight)(ref val)).weight2 = array6[2];
				((BoneWeight)(ref val)).weight3 = array6[3];
				array4[num5] = val;
			}
			int[] array7 = new int[num2];
			for (int num6 = 0; num6 < num2; num6++)
			{
				array7[num6] = binaryReader.ReadInt32();
				if (array7[num6] < 0 || array7[num6] >= num)
				{
					throw new InvalidDataException("Mesh index");
				}
			}
			Mesh val2 = new Mesh
			{
				name = Path.GetFileName(path),
				indexFormat = (IndexFormat)1
			};
			val2.vertices = array;
			val2.normals = array2;
			val2.uv = array3;
			val2.triangles = array7;
			val2.boneWeights = array4;
			Matrix4x4[] array8 = (Matrix4x4[])(object)new Matrix4x4[num3];
			for (int num7 = 0; num7 < num3; num7++)
			{
				for (int num8 = 0; num8 < 4; num8++)
				{
					for (int num9 = 0; num9 < 4; num9++)
					{
						((Matrix4x4)(ref array8[num7]))[num8, num9] = rig.bones[num7].bindpose[num8 * 4 + num9];
					}
				}
			}
			val2.bindposes = array8;
			val2.RecalculateBounds();
			val2.RecalculateTangents();
			return val2;
		}

		private static bool Finite(Vector3 v)
		{
			//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			if (!float.IsNaN(v.x + v.y + v.z))
			{
				return !float.IsInfinity(v.x + v.y + v.z);
			}
			return false;
		}

		private void OnDestroy()
		{
			BaseFireSnipe.onFireSnipe -= AdaptSniperMuzzle;
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplay));
			MainMenuController.OnMainMenuInitialised -= SyncDisplay;
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
	[DefaultExecutionOrder(31900)]
	public sealed class RailgunnerBounds : MonoBehaviour
	{
		[SerializeField]
		private SkinnedMeshRenderer target;

		[SerializeField]
		private Bounds original;

		[SerializeField]
		private bool originalOffscreen;

		private bool changed;

		public void Configure(SkinnedMeshRenderer r)
		{
			//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)
			target = r;
			original = ((Renderer)r).localBounds;
			originalOffscreen = r.updateWhenOffscreen;
		}

		private void LateUpdate()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target))
			{
				if (RailgunnerCollection.PresentationEnabled && RailgunnerCollection.AuthoredMeshes.Contains(target.sharedMesh))
				{
					SkinnedMeshRenderer obj = target;
					Bounds bounds = target.sharedMesh.bounds;
					Vector3 center = ((Bounds)(ref bounds)).center;
					bounds = target.sharedMesh.bounds;
					((Renderer)obj).localBounds = new Bounds(center, ((Bounds)(ref bounds)).size + Vector3.one * 3f);
					target.updateWhenOffscreen = true;
					changed = true;
				}
				else
				{
					Restore();
				}
			}
		}

		public void Release()
		{
			Restore();
		}

		private void Restore()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (changed && Object.op_Implicit((Object)(object)target))
			{
				((Renderer)target).localBounds = original;
				target.updateWhenOffscreen = originalOffscreen;
			}
			changed = false;
		}

		private void OnDisable()
		{
			Restore();
		}

		private void OnDestroy()
		{
			Restore();
		}
	}
	[DefaultExecutionOrder(-32000)]
	public sealed class RailgunnerMuzzle : MonoBehaviour
	{
		[SerializeField]
		private SkinnedMeshRenderer target;

		[SerializeField]
		private ChildLocator locator;

		[SerializeField]
		private Transform leaf;

		[SerializeField]
		private Transform parent;

		[SerializeField]
		private Vector3 originalPosition;

		private Vector3 lastWrittenPosition;

		private bool changed;

		private bool warnedValidation;

		private readonly List<Tuple<WeakReference<BaseFireSnipe>, string>> touched = new List<Tuple<WeakReference<BaseFireSnipe>, string>>();

		private void WarnValidation()
		{
			if (!warnedValidation)
			{
				warnedValidation = true;
				RailgunnerCollection.ReportMuzzleValidation("Expected existing MuzzleSniper index3 beneath GunEnd; native locator left unchanged on " + ((Object)((Component)this).gameObject).name);
			}
		}

		public void Configure(SkinnedMeshRenderer r, ChildLocator c)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			target = r;
			locator = c;
			if (!Object.op_Implicit((Object)(object)r) || r.bones.Length <= 104 || !Object.op_Implicit((Object)(object)c))
			{
				WarnValidation();
				return;
			}
			parent = r.bones[104];
			leaf = c.FindChild("MuzzleSniper");
			if (!Object.op_Implicit((Object)(object)leaf) || (Object)(object)leaf.parent != (Object)(object)parent || c.FindChildIndex("MuzzleSniper") != 3)
			{
				leaf = null;
				WarnValidation();
			}
			else
			{
				originalPosition = leaf.localPosition;
			}
		}

		public bool Ensure()
		{
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			if (!((Behaviour)this).isActiveAndEnabled || !RailgunnerCollection.PresentationEnabled || !Object.op_Implicit((Object)(object)target) || !Object.op_Implicit((Object)(object)target.sharedMesh) || !RailgunnerCollection.MuzzlePositions.TryGetValue(target.sharedMesh, out var value))
			{
				Restore();
				return false;
			}
			if (!Object.op_Implicit((Object)(object)leaf) || !Object.op_Implicit((Object)(object)parent) || (Object)(object)leaf.parent != (Object)(object)parent || !Object.op_Implicit((Object)(object)locator) || locator.FindChildIndex("MuzzleSniper") != 3 || (Object)(object)locator.FindChild("MuzzleSniper") != (Object)(object)leaf)
			{
				WarnValidation();
				Restore();
				return false;
			}
			leaf.localPosition = value;
			lastWrittenPosition = value;
			changed = true;
			return true;
		}

		public void Remember(BaseFireSnipe state)
		{
			if (!(((GenericBulletBaseState)state).muzzleName == "MuzzleSniper"))
			{
				touched.Add(Tuple.Create(new WeakReference<BaseFireSnipe>(state), ((GenericBulletBaseState)state).muzzleName));
			}
		}

		public void Release()
		{
			Restore();
		}

		private void Prune()
		{
			for (int num = touched.Count - 1; num >= 0; num--)
			{
				if (!touched[num].Item1.TryGetTarget(out var val) || (Object)(object)((EntityState)val).outer == (Object)null || (object)((EntityState)val).outer.state != val)
				{
					touched.RemoveAt(num);
				}
			}
		}

		private void OnEnable()
		{
			Ensure();
		}

		private void Update()
		{
			Ensure();
			Prune();
		}

		private void FixedUpdate()
		{
			Ensure();
		}

		private void LateUpdate()
		{
			Ensure();
		}

		private void Restore()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			if (changed && Object.op_Implicit((Object)(object)leaf) && (Object)(object)leaf.parent == (Object)(object)parent)
			{
				Vector3 val = leaf.localPosition - lastWrittenPosition;
				if (((Vector3)(ref val)).sqrMagnitude < 1E-12f)
				{
					leaf.localPosition = originalPosition;
				}
			}
			changed = false;
			foreach (Tuple<WeakReference<BaseFireSnipe>, string> item in touched)
			{
				if (item.Item1.TryGetTarget(out var val2) && ((GenericBulletBaseState)val2).muzzleName == "MuzzleSniper")
				{
					((GenericBulletBaseState)val2).muzzleName = item.Item2;
				}
			}
			touched.Clear();
		}

		private void OnDisable()
		{
			Restore();
		}

		private void OnDestroy()
		{
			Restore();
		}
	}
}
namespace Rodanius.Standalone
{
	public static class CatalogueSpecs
	{
		public static bool Matches(SkinRecord r)
		{
			switch (r.key)
			{
			case "acrid-bog-hopper":
				if (r.skinId == "EclipsePlaytestAcridE1BogHopper" && r.family == "single" && r.name == "Bog Hopper" && r.survivor == "Acrid")
				{
					return r.tier == 1;
				}
				return false;
			case "acrid-duck-and-cover":
				if (r.skinId == "EclipsePlaytestAcridE2DuckAndCover" && r.family == "single" && r.name == "Duck and Cover" && r.survivor == "Acrid")
				{
					return r.tier == 2;
				}
				return false;
			case "acrid-trash-panda":
				if (r.skinId == "EclipsePlaytestAcridE3TrashPanda" && r.family == "single" && r.name == "Trash Panda" && r.survivor == "Acrid")
				{
					return r.tier == 3;
				}
				return false;
			case "acrid-good-boy":
				if (r.skinId == "EclipsePlaytestAcridE4GoodBoy" && r.family == "single" && r.name == "Good Boy" && r.survivor == "Acrid")
				{
					return r.tier == 4;
				}
				return false;
			case "acrid-ginger-cat":
				if (r.skinId == "EclipsePlaytestAcridE5GingerCat" && r.family == "single" && r.name == "Ginger Cat" && r.survivor == "Acrid")
				{
					return r.tier == 5;
				}
				return false;
			case "acrid-squirrel":
				if (r.skinId == "EclipsePlaytestAcridE6Squirrel" && r.family == "single" && r.name == "Squirrel" && r.survivor == "Acrid")
				{
					return r.tier == 6;
				}
				return false;
			case "acrid-goat":
				if (r.skinId == "EclipsePlaytestAcridE7Goat" && r.family == "single" && r.name == "Goat" && r.survivor == "Acrid")
				{
					return r.tier == 7;
				}
				return false;
			case "acrid-abyssal-angler":
				if (r.skinId == "EclipsePlaytestAcridE8AbyssalAngler" && r.family == "single" && r.name == "Abyssal Angler" && r.survivor == "Acrid")
				{
					return r.tier == 8;
				}
				return false;
			case "bandit-corner-crew":
				if (r.skinId == "skinEclipsePlaytestBanditE1" && r.family == "single" && r.name == "Corner Crew" && r.survivor == "Bandit")
				{
					return r.tier == 1;
				}
				return false;
			case "bandit-after-hours":
				if (r.skinId == "skinEclipsePlaytestBanditE2" && r.family == "single" && r.name == "After Hours" && r.survivor == "Bandit")
				{
					return r.tier == 2;
				}
				return false;
			case "bandit-house-always-wins":
				if (r.skinId == "skinEclipsePlaytestBanditE3" && r.family == "single" && r.name == "House Always Wins" && r.survivor == "Bandit")
				{
					return r.tier == 3;
				}
				return false;
			case "bandit-card-shark":
				if (r.skinId == "skinEclipsePlaytestBanditE5" && r.family == "single" && r.name == "Card Shark" && r.survivor == "Bandit")
				{
					return r.tier == 5;
				}
				return false;
			case "chef-crab-rangoon":
				if (r.skinId == "EclipsePlaytestChefE2CrabRangoon" && r.family == "single" && r.name == "Crab Rangoon" && r.survivor == "CHEF")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-frontier-recruit":
				if (r.skinId == "skinEclipsePlaytestCommandoE1" && r.family == "single" && r.name == "Frontier Recruit" && r.survivor == "Commando")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-vacuum-breacher":
				if (r.skinId == "skinEclipsePlaytestCommandoE2" && r.family == "single" && r.name == "Vacuum Breacher" && r.survivor == "Commando")
				{
					return r.tier == 2;
				}
				return false;
			case "commando-expedition-marshal":
				if (r.skinId == "skinEclipsePlaytestCommandoE3" && r.family == "single" && r.name == "Expedition Marshal" && r.survivor == "Commando")
				{
					return r.tier == 3;
				}
				return false;
			case "commando-clockwork-infantry":
				if (r.skinId == "skinEclipsePlaytestCommandoE4" && r.family == "single" && r.name == "Clockwork Infantry" && r.survivor == "Commando")
				{
					return r.tier == 4;
				}
				return false;
			case "commando-action-figure":
				if (r.skinId == "skinEclipsePlaytestCommandoE5" && r.family == "single" && r.name == "Action Figure" && r.survivor == "Commando")
				{
					return r.tier == 5;
				}
				return false;
			case "commando-quartermaster":
				if (r.skinId == "skinEclipsePlaytestCommandoE6" && r.family == "single" && r.name == "Quartermaster" && r.survivor == "Commando")
				{
					return r.tier == 6;
				}
				return false;
			case "commando-one-man-band":
				if (r.skinId == "skinEclipsePlaytestCommandoE7" && r.family == "single" && r.name == "One-Man Band" && r.survivor == "Commando")
				{
					return r.tier == 7;
				}
				return false;
			case "commando-extinction-protocol":
				if (r.skinId == "skinEclipsePlaytestCommandoE8" && r.family == "single" && r.name == "Extinction Protocol" && r.survivor == "Commando")
				{
					return r.tier == 8;
				}
				return false;
			case "drifter-happy-camper":
				if (r.skinId == "EclipsePlaytestDrifterE1HappyCamper" && r.family == "single" && r.name == "Happy Camper" && r.survivor == "Drifter")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-union-builder":
				if (r.skinId == "skinEclipsePlaytestEngineerE1_union-builder" && r.family == "single" && r.name == "Union Builder" && r.survivor == "Engineer")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-mine-surveyor":
				if (r.skinId == "skinEclipsePlaytestEngineerE2_mine-surveyor" && r.family == "single" && r.name == "Mine Surveyor" && r.survivor == "Engineer")
				{
					return r.tier == 2;
				}
				return false;
			case "false-son-penguin":
				if (r.skinId == "EclipsePlaytestFalseSonE3Penguin" && r.family == "single" && r.name == "Penguin" && r.survivor == "False Son")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-hare-trigger":
				if (r.skinId == "skinEclipseHuntressNewSkins_hare-trigger" && r.family == "huntress" && r.name == "Hare Trigger" && r.survivor == "Huntress")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-pink-slip":
				if (r.skinId == "skinEclipseHuntressNewSkins_pink-slip" && r.family == "huntress" && r.name == "Pink Slip" && r.survivor == "Huntress")
				{
					return r.tier == 2;
				}
				return false;
			case "huntress-wallflower":
				if (r.skinId == "skinEclipseHuntressNewSkins_wallflower" && r.family == "huntress" && r.name == "Wallflower" && r.survivor == "Huntress")
				{
					return r.tier == 3;
				}
				return false;
			case "huntress-shell-shock":
				if (r.skinId == "skinEclipseHuntressNewSkins_shell-shock" && r.family == "huntress" && r.name == "Shell Shock" && r.survivor == "Huntress")
				{
					return r.tier == 4;
				}
				return false;
			case "huntress-hot-pursuit":
				if (r.skinId == "skinEclipseHuntressNewSkins_hot-pursuit" && r.family == "huntress" && r.name == "Hot Pursuit" && r.survivor == "Huntress")
				{
					return r.tier == 5;
				}
				return false;
			case "huntress-banana":
				if (r.skinId == "skinHuntressLiquidAssetsPlaytest_liquid-assets" && r.family == "single" && r.name == "Banana" && r.survivor == "Huntress")
				{
					return r.tier == 6;
				}
				return false;
			case "huntress-loose-ends":
				if (r.skinId == "skinEclipseHuntressNewSkins_loose-ends" && r.family == "huntress" && r.name == "Loose Ends" && r.survivor == "Huntress")
				{
					return r.tier == 7;
				}
				return false;
			case "huntress-dawnstrider":
				if (r.skinId == "skinEclipseHuntressNewSkins_dawnstrider" && r.family == "huntress" && r.name == "Dawnstrider" && r.survivor == "Huntress")
				{
					return r.tier == 8;
				}
				return false;
			case "loader-go-fetch":
				if (r.skinId == "EclipseLoaderE1" && r.family == "loader" && r.name == "Go Fetch" && r.survivor == "Loader")
				{
					return r.tier == 1;
				}
				return false;
			case "loader-bear-knuckle":
				if (r.skinId == "EclipseLoaderE2" && r.family == "loader" && r.name == "Bear Knuckle" && r.survivor == "Loader")
				{
					return r.tier == 2;
				}
				return false;
			case "loader-knuckle-dragger":
				if (r.skinId == "EclipseLoaderE3" && r.family == "loader" && r.name == "Knuckle Dragger" && r.survivor == "Loader")
				{
					return r.tier == 3;
				}
				return false;
			case "loader-brick-house":
				if (r.skinId == "EclipseLoaderE4" && r.family == "loader" && r.name == "Brick House" && r.survivor == "Loader")
				{
					return r.tier == 4;
				}
				return false;
			case "loader-dead-weight":
				if (r.skinId == "EclipseLoaderE5" && r.family == "loader" && r.name == "Dead Weight" && r.survivor == "Loader")
				{
					return r.tier == 5;
				}
				return false;
			case "loader-rubber-bandit":
				if (r.skinId == "EclipseLoaderE6" && r.family == "loader" && r.name == "Rubber Bandit" && r.survivor == "Loader")
				{
					return r.tier == 6;
				}
				return false;
			case "loader-high-five":
				if (r.skinId == "EclipseLoaderE7" && r.family == "loader" && r.name == "High Five" && r.survivor == "Loader")
				{
					return r.tier == 7;
				}
				return false;
			case "loader-titan-champion":
				if (r.skinId == "EclipseLoaderE8" && r.family == "loader" && r.name == "Titan Champion" && r.survivor == "Loader")
				{
					return r.tier == 8;
				}
				return false;
			case "mul-t-yard-salvager":
				if (r.skinId == "skinEclipsePlaytest_MULT_E1" && r.family == "single" && r.name == "Yard Salvager" && r.survivor == "MUL-T")
				{
					return r.tier == 1;
				}
				return false;
			case "mul-t-timber-hauler":
				if (r.skinId == "skinEclipsePlaytest_MULT_E2" && r.family == "single" && r.name == "Timber Hauler" && r.survivor == "MUL-T")
				{
					return r.tier == 2;
				}
				return false;
			case "mul-t-deep-salvage-unit":
				if (r.skinId == "skinEclipsePlaytest_MULT_E3" && r.family == "single" && r.name == "Deep-Salvage Unit" && r.survivor == "MUL-T")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-roadworn-ronin":
				if (r.skinId == "EclipsePlaytestMercenaryE1RoadwornRonin" && r.family == "single" && r.name == "Roadworn Ronin" && r.survivor == "Mercenary")
				{
					return r.tier == 1;
				}
				return false;
			case "mercenary-canopy-cutter":
				if (r.skinId == "EclipsePlaytestMercenaryE3CanopyCutter" && r.family == "single" && r.name == "Canopy Cutter" && r.survivor == "Mercenary")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-circuit-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE2CircuitDuelist" && r.family == "single" && r.name == "Circuit Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 2;
				}
				return false;
			case "mercenary-deli-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE7DeliDuelist" && r.family == "single" && r.name == "Deli Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 7;
				}
				return false;
			case "rex-prickly-customer":
				if (r.skinId == "skinEclipseRexPricklyCustomer" && r.family == "single" && r.name == "Prickly Customer" && r.survivor == "REX")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-hole-in-one":
				if (r.skinId == "EclipseRailgunnerE1" && r.family == "railgunner" && r.name == "Hole in One" && r.survivor == "Railgunner")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-night-sight":
				if (r.skinId == "EclipseRailgunnerE2" && r.family == "railgunner" && r.name == "Night Sight" && r.survivor == "Railgunner")
				{
					return r.tier == 2;
				}
				return false;
			case "railgunner-ring-leader":
				if (r.skinId == "EclipseRailgunnerE3" && r.family == "railgunner" && r.name == "Ring Leader" && r.survivor == "Railgunner")
				{
					return r.tier == 3;
				}
				return false;
			case "railgunner-fire-away":
				if (r.skinId == "EclipseRailgunnerE4" && r.family == "railgunner" && r.name == "Fire Away" && r.survivor == "Railgunner")
				{
					return r.tier == 4;
				}
				return false;
			case "railgunner-point-taken":
				if (r.skinId == "EclipseRailgunnerE5" && r.family == "railgunner" && r.name == "Point Taken" && r.survivor == "Railgunner")
				{
					return r.tier == 5;
				}
				return false;
			case "railgunner-express-delivery":
				if (r.skinId == "EclipseRailgunnerE6" && r.family == "railgunner" && r.name == "Express Delivery" && r.survivor == "Railgunner")
				{
					return r.tier == 6;
				}
				return false;
			case "railgunner-last-straw":
				if (r.skinId == "EclipseRailgunnerE7" && r.family == "railgunner" && r.name == "Last Straw" && r.survivor == "Railgunner")
				{
					return r.tier == 7;
				}
				return false;
			case "railgunner-horizon-lancer":
				if (r.skinId == "EclipseRailgunnerE8" && r.family == "railgunner" && r.name == "Horizon Lancer" && r.survivor == "Railgunner")
				{
					return r.tier == 8;
				}
				return false;
			case "seeker-breaditation":
				if (r.skinId == "EclipsePlaytestSeekerE7Breaditation" && r.family == "single" && r.name == "Breaditation" && r.survivor == "Seeker")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-desert-castaway":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE1" && r.family == "single" && r.name == "Desert Castaway" && r.survivor == "Void Fiend")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-live-wire":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE2" && r.family == "single" && r.name == "Live Wire" && r.survivor == "Void Fiend")
				{
					return r.tier == 2;
				}
				return false;
			case "void-fiend-pressure-guest":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE3" && r.family == "single" && r.name == "Pressure Guest" && r.survivor == "Void Fiend")
				{
					return r.tier == 3;
				}
				return false;
			case "void-fiend-orange-you-glad":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE4" && r.family == "single" && r.name == "Orange You Glad" && r.survivor == "Void Fiend")
				{
					return r.tier == 4;
				}
				return false;
			case "void-fiend-burnt-offering":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE5" && r.family == "single" && r.name == "Burnt Offering" && r.survivor == "Void Fiend")
				{
					return r.tier == 5;
				}
				return false;
			case "void-fiend-public-information":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE6" && r.family == "single" && r.name == "Public Information" && r.survivor == "Void Fiend")
				{
					return r.tier == 6;
				}
				return false;
			case "void-fiend-surprise-inside":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE7" && r.family == "single" && r.name == "Surprise Inside" && r.survivor == "Void Fiend")
				{
					return r.tier == 7;
				}
				return false;
			case "void-fiend-containment-impossible":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE8" && r.family == "single" && r.name == "Containment Impossible" && r.survivor == "Void Fiend")
				{
					return r.tier == 8;
				}
				return false;
			default:
				return false;
			}
		}
	}
	[Serializable]
	public sealed class AssetFile
	{
		public string path;

		public string sha256;
	}
	[Serializable]
	public sealed class SkinRecord
	{
		public int schema;

		public int tier;

		public string key;

		public string name;

		public string survivor;

		public string family;

		public string skinId;

		public string assetDirectory;

		public string icon;

		public string iconSha256;

		public AssetFile[] files;

		[NonSerialized]
		public string Root;

		public string AssetRoot => SkinDiscovery.SafePath(Root, assetDirectory);
	}
	public static class SkinDiscovery
	{
		public static string SafePath(string root, string relative)
		{
			if (string.IsNullOrEmpty(relative) || Path.IsPathRooted(relative) || relative.Split('/', '\\').Any((string x) => x == ".." || x == ""))
			{
				throw new InvalidDataException("Invalid package-relative path");
			}
			string text = Path.GetFullPath(root).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
			string fullPath = Path.GetFullPath(Path.Combine(root, relative));
			if (!fullPath.StartsWith(text, StringComparison.OrdinalIgnoreCase) && fullPath != text.TrimEnd(Path.DirectorySeparatorChar))
			{
				throw new InvalidDataException("Package path escaped root");
			}
			return fullPath;
		}

		private static IEnumerable<string> FindRecords(string root, Action<string> log)
		{
			Stack<string> todo = new Stack<string>();
			todo.Push(root);
			while (todo.Count > 0)
			{
				string dir = todo.Pop();
				string text = Path.Combine(dir, "rodanius-skin.json");
				if (File.Exists(text))
				{
					yield return text;
				}
				string[] directories;
				try
				{
					directories = Directory.GetDirectories(dir);
				}
				catch (Exception ex)
				{
					log("RODANIUS_DISCOVERY_SKIPPED " + dir + " " + ex.Message);
					continue;
				}
				string[] array = directories;
				foreach (string text2 in array)
				{
					try
					{
						if ((File.GetAttributes(text2) & FileAttributes.ReparsePoint) == 0)
						{
							todo.Push(text2);
						}
					}
					catch (Exception ex2)
					{
						log("RODANIUS_DISCOVERY_SKIPPED " + ex2.Message);
					}
				}
			}
		}

		public static string Hash(string path)
		{
			using FileStream inputStream = File.OpenRead(path);
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant();
		}

		public static List<SkinRecord> Load(string family, Action<string> log, bool verifyAssets = true)
		{
			List<SkinRecord> list = new List<SkinRecord>();
			foreach (string item in FindRecords(Paths.PluginPath, log))
			{
				try
				{
					if (new FileInfo(item).Length > 262144)
					{
						throw new InvalidDataException("Manifest too large");
					}
					SkinRecord skinRecord = JsonUtility.FromJson<SkinRecord>(File.ReadAllText(item));
					if (skinRecord == null || skinRecord.schema != 1 || !CatalogueSpecs.Matches(skinRecord))
					{
						throw new InvalidDataException("Unknown standalone skin identity");
					}
					if (family != null && skinRecord.family != family)
					{
						continue;
					}
					skinRecord.Root = Path.GetDirectoryName(item);
					SafePath(skinRecord.Root, skinRecord.assetDirectory);
					SafePath(skinRecord.Root, skinRecord.icon);
					if (verifyAssets)
					{
						if (skinRecord.files == null || skinRecord.files.Length == 0 || skinRecord.files.Length > 100)
						{
							throw new InvalidDataException("Asset inventory missing");
						}
						AssetFile[] files = skinRecord.files;
						foreach (AssetFile assetFile in files)
						{
							if (assetFile == null || assetFile.sha256 == null || assetFile.sha256.Length != 64 || Hash(SafePath(skinRecord.Root, assetFile.path)) != assetFile.sha256)
							{
								throw new InvalidDataException("Asset hash mismatch: " + ((assetFile == null) ? "null" : assetFile.path));
							}
						}
					}
					list.Add(skinRecord);
				}
				catch (Exception ex)
				{
					log("RODANIUS_SKIN_PACKAGE_REJECTED file=" + item + " error=" + ex.Message);
				}
			}
			List<SkinRecord> list2 = new List<SkinRecord>();
			foreach (IGrouping<string, SkinRecord> item2 in list.GroupBy<SkinRecord, string>((SkinRecord r) => r.skinId, StringComparer.Ordinal))
			{
				if (item2.Count() != 1)
				{
					log("RODANIUS_DUPLICATE_SKIN_PACKAGE id=" + item2.Key + " paths=" + string.Join(";", item2.Select((SkinRecord r) => r.Root)));
				}
				else
				{
					list2.Add(item2.Single());
				}
			}
			return list2.OrderBy<SkinRecord, string>((SkinRecord r) => r.survivor, StringComparer.Ordinal).ThenBy((SkinRecord r) => r.tier).ToList();
		}
	}
}

BepInEx/plugins/RodaniusSkinRuntime/EclipseHuntressNewSkins.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using EclipseSkinRuntimeFix;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
using Rodanius.Standalone;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Rendering;
using UnityEngine.ResourceManagement.AsyncOperations;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: AssemblyVersion("0.0.0.0")]
namespace EclipseSkinRuntimeFix
{
	internal sealed class HuntressMaterialProbe : MonoBehaviour
	{
		private SkinnedMeshRenderer target;

		private string previous;

		public static void Attach(SkinnedMeshRenderer renderer)
		{
			if (Object.op_Implicit((Object)(object)renderer))
			{
				(((Component)renderer).GetComponent<HuntressMaterialProbe>() ?? ((Component)renderer).gameObject.AddComponent<HuntressMaterialProbe>()).target = renderer;
			}
		}

		private void Awake()
		{
			target = ((Component)this).GetComponent<SkinnedMeshRenderer>();
		}

		private void LateUpdate()
		{
			if (!Object.op_Implicit((Object)(object)target))
			{
				target = ((Component)this).GetComponent<SkinnedMeshRenderer>();
			}
			if (Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)target.sharedMesh))
			{
				Material sharedMaterial = ((Renderer)target).sharedMaterial;
				Texture val = ((Object.op_Implicit((Object)(object)sharedMaterial) && sharedMaterial.HasProperty("_MainTex")) ? sharedMaterial.GetTexture("_MainTex") : null);
				string text = ((Object)target.sharedMesh).name + "#" + ((Object)target.sharedMesh).GetInstanceID() + " material=" + (Object.op_Implicit((Object)(object)sharedMaterial) ? (((Object)sharedMaterial).name + "#" + ((Object)sharedMaterial).GetInstanceID()) : "null") + " shader=" + ((Object.op_Implicit((Object)(object)sharedMaterial) && Object.op_Implicit((Object)(object)sharedMaterial.shader)) ? ((Object)sharedMaterial.shader).name : "null") + " albedo=" + (Object.op_Implicit((Object)(object)val) ? (((Object)val).name + "#" + ((Object)val).GetInstanceID()) : "null");
				if (!(text == previous))
				{
					previous = text;
					Debug.Log((object)("ECLIPSE_HUNTRESS_APPLIED mesh=" + text + " renderer=" + ((Object)target).name));
				}
			}
		}

		private void OnDisable()
		{
			previous = null;
		}
	}
	internal static class NativeRenderers
	{
		private static readonly HashSet<string> NativePaths = new HashSet<string>(StringComparer.Ordinal)
		{
			"mdlLoader/PilotFemaleMesh", "mdlLoader/LoaderMechMesh", "mdlLoader/PilotFemaleFoldedOverJumpsuit", "mdlFalseSon/FalseSon_Body", "mdlFalseSon/FalseSon_Cloth", "mdlFalseSon/L_FalseSon_Weapon", "mdlSeeker/meshSeekerBody", "mdlSeeker/meshSeekerCloth", "mdlSeeker/meshSeekerGlass", "mdlChef/meshChef",
			"mdlChef/meshChefPizzaCutter", "mdlChef/meshlChefCleaver", "mdlChef/meshChefOven", "mdlChef/meshChefIceBox", "mdlCroco/CrocoMesh", "mdlCroco/CrocoSpineMesh", "mdlHuntress/HuntressMesh", "mdlHuntress/BowMesh", "mdlHuntress/HuntressScarfMesh", "mdlHuntress (1)/HuntressMesh",
			"mdlHuntress (1)/BowMesh", "mdlHuntress (1)/HuntressScarfMesh", "mdlMerc/MercMesh", "mdlMerc/MercSwordMesh", "mdlTreebot/TreebotBotMesh", "mdlTreebot/TreebotRootMesh", "mdlTreebot/TreebotLeafletMesh", "mdlTreebot/TreebotFlowerMesh", "mdlVoidSurvivor/mdlVoidSurvivorBody", "mdlVoidSurvivor/mdlVoidSurvivorHead",
			"mdlVoidSurvivor/mdlVoidSurvivorMetal", "mdlVoidSurvivor/metalcollar.001", "mdlBandit2/BanditArmature/ROOT/base/MainWeapon/BanditShotgunMesh", "mdlBandit2/BanditArmature/SideWeapon/SideWeaponSpinner/BanditPistolMesh", "mdlBandit2/Bandit2AccessoriesMesh"
		};

		public static T[] GetSkinRenderers<T>(this Component owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer
		{
			return owner.gameObject.GetSkinRenderers<T>(inactive, parameters);
		}

		public static T[] GetSkinRenderers<T>(this GameObject owner, bool inactive = false, SkinDefParams parameters = null) where T : Renderer
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			T[] componentsInChildren = owner.GetComponentsInChildren<T>(inactive);
			CharacterModel val = owner.GetComponent<CharacterModel>() ?? owner.GetComponentInParent<CharacterModel>();
			ModelSkinController val2 = owner.GetComponent<ModelSkinController>() ?? (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ModelSkinController>() : null);
			HashSet<Renderer> skinRefs = new HashSet<Renderer>();
			SkinDefParams val3 = parameters;
			if (!Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val2) && val2.skins != null && val2.skins.Length != 0 && Object.op_Implicit((Object)(object)val2.skins[0]))
			{
				val3 = val2.skins[0].skinDefParams;
			}
			if (Object.op_Implicit((Object)(object)val3))
			{
				if (val3.rendererInfos != null)
				{
					RendererInfo[] rendererInfos = val3.rendererInfos;
					foreach (RendererInfo val4 in rendererInfos)
					{
						if (Object.op_Implicit((Object)(object)val4.renderer))
						{
							skinRefs.Add(val4.renderer);
						}
					}
				}
				if (val3.meshReplacements != null)
				{
					MeshReplacement[] meshReplacements = val3.meshReplacements;
					foreach (MeshReplacement val5 in meshReplacements)
					{
						if (Object.op_Implicit((Object)(object)val5.renderer))
						{
							skinRefs.Add(val5.renderer);
						}
					}
				}
			}
			HashSet<Renderer> modelRefs = new HashSet<Renderer>();
			if (Object.op_Implicit((Object)(object)val) && val.baseRendererInfos != null)
			{
				RendererInfo[] rendererInfos = val.baseRendererInfos;
				foreach (RendererInfo val6 in rendererInfos)
				{
					if (Object.op_Implicit((Object)(object)val6.renderer))
					{
						modelRefs.Add(val6.renderer);
					}
				}
			}
			return Select(componentsInChildren, (T x) => ((Object)(object)x).name, (T x) => skinRefs.Contains((Renderer)(object)x), (T x) => modelRefs.Contains((Renderer)(object)x), (T x) => Path(((Component)(object)x).transform, owner.transform), (T x) => IsKnownNativePath(Path(((Component)(object)x).transform, owner.transform)));
		}

		internal static T[] Select<T>(T[] found, Func<T, string> name, Func<T, bool> skin, Func<T, bool> model, Func<T, string> path, Func<T, bool> contract = null)
		{
			HashSet<T> hashSet = new HashSet<T>();
			if (contract == null)
			{
				contract = (T x) => false;
			}
			bool flag = found.Any(skin) || found.Any(model) || found.Any(contract);
			foreach (IGrouping<string, T> item in found.GroupBy(name))
			{
				T[] array = item.ToArray();
				if (array.Length == 1)
				{
					if (!flag || skin(array[0]) || model(array[0]) || contract(array[0]))
					{
						hashSet.Add(array[0]);
					}
					continue;
				}
				T[] array2 = array.Where(skin).ToArray();
				T[] array3 = array.Where(model).ToArray();
				T[] array4 = ((array2.Length == 1) ? ((array3.Length == 0 || array3.Contains(array2[0])) ? array2 : new T[0]) : ((array2.Length <= 1) ? array3 : array2.Where(((IEnumerable<T>)array3).Contains<T>).ToArray()));
				if (array2.Length == 0 && array3.Length == 0)
				{
					T[] array5 = array.Where(contract).ToArray();
					if (array5.Length != 0)
					{
						if (array5.Length != 1)
						{
							throw new InvalidOperationException("ECLIPSE_RENDERER_PATH_AMBIGUOUS " + string.Join(";", array.Select(path)));
						}
						hashSet.Add(array5[0]);
						Debug.Log((object)("ECLIPSE_RENDERER_NATIVE_PATH name=" + item.Key + " native=" + path(array5[0])));
						continue;
					}
				}
				if (array2.Length == 0 && array3.Length == 0 && flag)
				{
					Debug.Log((object)("ECLIPSE_RENDERER_FOREIGN_DUPLICATES name=" + item.Key + " ignored=" + array.Length));
					continue;
				}
				if (array4.Length != 1)
				{
					throw new InvalidOperationException("ECLIPSE_RENDERER_AMBIGUOUS name=" + item.Key + " candidates=" + string.Join(";", array.Select(path)) + " skinRefs=" + array2.Length + " modelRefs=" + array3.Length);
				}
				hashSet.Add(array4[0]);
				Debug.Log((object)("ECLIPSE_RENDERER_RESOLVED name=" + item.Key + " native=" + path(array4[0]) + " ignoredDuplicates=" + (array.Length - 1)));
			}
			return found.Where(hashSet.Contains).ToArray();
		}

		internal static bool IsKnownNativePath(string path)
		{
			if (path == null)
			{
				return false;
			}
			int num = path.IndexOf('/');
			if (num < 0)
			{
				return false;
			}
			string text = path.Substring(0, num);
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = text.Substring(0, text.Length - 7);
			}
			return NativePaths.Contains(text + path.Substring(num));
		}

		private static string Path(Transform t, Transform root)
		{
			List<string> list = new List<string>();
			Transform val = t;
			while (Object.op_Implicit((Object)(object)val))
			{
				list.Add(((Object)val).name);
				if ((Object)(object)val == (Object)(object)root)
				{
					break;
				}
				val = val.parent;
			}
			list.Reverse();
			return string.Join("/", list);
		}
	}
}
namespace EclipseHuntressRework
{
	[BepInPlugin("eclipse.huntress.rework20261025", "Eclipse Huntress New Skins", "0.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class EclipseHuntressNewSkins : BaseUnityPlugin
	{
		private sealed class Design
		{
			public string Slug;

			public string Name;

			public Color32[] Colors;

			public Design(string slug, string name, Color32[] colors)
			{
				Slug = slug;
				Name = name;
				Colors = colors;
			}
		}

		public const string Guid = "eclipse.huntress.rework20261025";

		public const string Version = "0.2.0";

		private static EclipseHuntressNewSkins instance;

		private readonly List<AsyncOperationHandle> retainedAssets = new List<AsyncOperationHandle>();

		private float registrationDeadline;

		private string folder;

		private SkinDef skin;

		private Mesh mesh;

		private Material material;

		private GameObject modelPrefab;

		private int rendererIndex;

		private bool registered;

		private static readonly Design[] Designs = new Design[7]
		{
			new Design("hare-trigger", "Huntress - Hare Trigger", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)132, (byte)82, (byte)48, byte.MaxValue),
				new Color32((byte)230, (byte)205, (byte)163, byte.MaxValue),
				new Color32((byte)188, (byte)80, (byte)42, byte.MaxValue),
				new Color32((byte)57, (byte)40, (byte)27, byte.MaxValue)
			}),
			new Design("pink-slip", "Huntress - Pink Slip", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)244, (byte)107, (byte)128, byte.MaxValue),
				new Color32(byte.MaxValue, (byte)158, (byte)161, byte.MaxValue),
				new Color32((byte)240, (byte)105, (byte)71, byte.MaxValue),
				new Color32((byte)63, (byte)42, (byte)49, byte.MaxValue)
			}),
			new Design("wallflower", "Huntress - Wallflower", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)244, (byte)146, (byte)54, byte.MaxValue),
				new Color32((byte)37, (byte)181, (byte)174, byte.MaxValue),
				new Color32((byte)239, (byte)211, (byte)171, byte.MaxValue),
				new Color32((byte)63, (byte)46, (byte)32, byte.MaxValue)
			}),
			new Design("shell-shock", "Huntress - Shell Shock", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)244, (byte)113, (byte)85, byte.MaxValue),
				new Color32(byte.MaxValue, (byte)166, (byte)124, byte.MaxValue),
				new Color32((byte)245, (byte)213, (byte)177, byte.MaxValue),
				new Color32((byte)123, (byte)46, (byte)37, byte.MaxValue)
			}),
			new Design("hot-pursuit", "Huntress - Hot Pursuit", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)239, (byte)47, (byte)24, byte.MaxValue),
				new Color32((byte)249, (byte)70, (byte)35, byte.MaxValue),
				new Color32((byte)107, (byte)154, (byte)26, byte.MaxValue),
				new Color32((byte)106, (byte)28, (byte)41, byte.MaxValue)
			}),
			new Design("loose-ends", "Huntress - Loose Ends", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)157, (byte)46, (byte)67, byte.MaxValue),
				new Color32((byte)199, (byte)67, (byte)87, byte.MaxValue),
				new Color32((byte)238, (byte)220, (byte)186, byte.MaxValue),
				new Color32((byte)81, (byte)21, (byte)37, byte.MaxValue)
			}),
			new Design("dawnstrider", "Huntress - Dawnstrider", (Color32[])(object)new Color32[4]
			{
				new Color32((byte)234, (byte)227, (byte)205, byte.MaxValue),
				new Color32((byte)222, (byte)79, (byte)70, byte.MaxValue),
				new Color32((byte)13, (byte)135, (byte)144, byte.MaxValue),
				new Color32((byte)19, (byte)213, (byte)239, byte.MaxValue)
			})
		};

		private void Awake()
		{
			folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
			instance = this;
			SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(EclipseHuntressNewSkins));
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
			MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
		}

		private void OnDestroy()
		{
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins));
			MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins;
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}

		[SystemInitializer(new Type[] { typeof(BodyCatalog) })]
		private static IEnumerator InitializeSkin()
		{
			if (!Object.op_Implicit((Object)(object)instance))
			{
				yield break;
			}
			instance.registrationDeadline = Time.realtimeSinceStartup + 45f;
			IEnumerator routine = instance.RegisterAsync();
			while (true)
			{
				bool flag;
				try
				{
					flag = routine.MoveNext();
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)instance).Logger.LogError((object)("ECLIPSE_HUNTRESS_REWORK_REGISTRATION_FAILED: " + ex));
					break;
				}
				if (!flag)
				{
					break;
				}
				yield return null;
			}
			(routine as IDisposable)?.Dispose();
		}

		private IEnumerator RegisterAsync()
		{
			List<SkinRecord> installed = SkinDiscovery.Load("huntress", delegate(string m)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)m);
			});
			if (installed.Count == 0)
			{
				yield break;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSE_HUNTRESS_REWORK_REGISTRATION_BEGIN async loader 0.2.0");
			GameObject val = BodyCatalog.FindBodyPrefab("HuntressBody");
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("HuntressBody is missing.");
			}
			modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
			ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
			SkinDef baseSkin = controller.skins[0];
			SkinDefParams baseParams = baseSkin.skinDefParams;
			if (!Object.op_Implicit((Object)(object)baseParams) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<SkinDefParams> load = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(load));
				while (!load.IsDone)
				{
					CheckLoadDeadline("skin parameters");
					yield return null;
				}
				baseParams = load.Result;
			}
			if (!Object.op_Implicit((Object)(object)baseParams))
			{
				throw new InvalidOperationException("Huntress's base skin parameters are unavailable.");
			}
			SkinnedMeshRenderer[] renderers = modelPrefab.GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, baseParams);
			SkinnedMeshRenderer target = renderers.First((SkinnedMeshRenderer r) => ((Object)r).name == "HuntressMesh" && r.bones.Length == 69 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
			HuntressMaterialProbe.Attach(target);
			rendererIndex = Array.IndexOf(renderers, target);
			Mesh referenceMesh = target.sharedMesh;
			if (!Object.op_Implicit((Object)(object)referenceMesh))
			{
				MeshReplacement val2 = baseParams.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
				referenceMesh = val2.mesh;
				if (!Object.op_Implicit((Object)(object)referenceMesh))
				{
					AsyncOperationHandle<Mesh> load2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
					retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(load2));
					while (!load2.IsDone)
					{
						CheckLoadDeadline("reference mesh");
						yield return null;
					}
					referenceMesh = load2.Result;
				}
			}
			if (!Object.op_Implicit((Object)(object)referenceMesh) || referenceMesh.bindposes.Length != target.bones.Length)
			{
				throw new InvalidOperationException("The installed Huntress bind pose does not match the renderer.");
			}
			RendererInfo originalInfo = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material val3 = originalInfo.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)val3) && originalInfo.defaultMaterialAddress != null)
			{
				AsyncOperationHandle<Material> load3 = Addressables.LoadAssetAsync<Material>(((AssetReference)originalInfo.defaultMaterialAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(load3));
				while (!load3.IsDone)
				{
					CheckLoadDeadline("material");
					yield return null;
				}
				val3 = load3.Result;
			}
			if (!Object.op_Implicit((Object)(object)val3))
			{
				val3 = ((Renderer)target).sharedMaterial;
			}
			if (!Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.shader))
			{
				throw new InvalidOperationException("Huntress's game shader is unavailable.");
			}
			AsyncOperationHandle<Shader> shaderLoad = Addressables.LoadAssetAsync<Shader>((object)"RoR2/Base/Shaders/HGStandard.shader");
			retainedAssets.Add(AsyncOperationHandle<Shader>.op_Implicit(shaderLoad));
			while (!shaderLoad.IsDone)
			{
				CheckLoadDeadline("HGStandard shader");
				yield return null;
			}
			if ((int)shaderLoad.Status != 1 || !Object.op_Implicit((Object)(object)shaderLoad.Result))
			{
				throw new InvalidOperationException("ECLIPSE_HUNTRESS_SHADER_LOAD_FAILED HGStandard");
			}
			Shader result = shaderLoad.Result;
			List<SkinDef> list = new List<SkinDef>();
			foreach (Design design in Designs.Where((Design d) => installed.Any((SkinRecord r) => r.key == "huntress-" + d.Slug)))
			{
				if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipseHuntressNewSkins_" + design.Slug))
				{
					continue;
				}
				try
				{
					string assetRoot = installed.Single((SkinRecord r) => r.key == "huntress-" + design.Slug).AssetRoot;
					mesh = ReadMesh(Path.Combine(assetRoot, "model.meshbin"), target, referenceMesh);
					((Object)mesh).name = "EclipseHuntressNewSkins_" + design.Slug;
					material = new Material(result)
					{
						name = "matEclipseHuntressNewSkins_" + design.Slug
					};
					material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine(assetRoot, "albedo-spec.png"), linear: false));
					material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine(assetRoot, "normal.png"), linear: true));
					if (!material.HasProperty("_MainTex") || !Object.op_Implicit((Object)(object)material.GetTexture("_MainTex")))
					{
						throw new InvalidOperationException("ECLIPSE_HUNTRESS_ALBEDO_BINDING_FAILED " + design.Slug);
					}
					material.SetTextureScale("_MainTex", Vector2.one);
					material.SetTextureOffset("_MainTex", Vector2.zero);
					material.SetColor("_EmColor", Color.white);
					material.SetFloat("_Cull", 2f);
					material.SetFloat("_ZWrite", 1f);
					material.SetFloat("_DitherOn", 1f);
					material.EnableKeyword("DITHER");
					material.SetColor("_Color", Color.white);
					material.SetFloat("_NormalStrength", 0f);
					material.SetFloat("_Smoothness", 0.15f);
					material.SetFloat("_SpecularStrength", 0.2f);
					material.SetFloat("_SpecularExponent", 4f);
					material.SetFloat("_EmPower", 1f);
					material.SetTexture("_EmTex", (Texture)(object)ReadTexture(Path.Combine(assetRoot, "emission.png"), linear: false));
					material.DisableKeyword("LIMBREMOVAL");
					material.SetFloat("_LimbRemovalOn", 0f);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_HUNTRESS_MATERIAL_READY skin=" + design.Slug + " shader=" + ((Object)material.shader).name + " albedo=" + ((Object)material.GetTexture("_MainTex")).name));
					RendererInfo val4 = originalInfo;
					val4.defaultMaterial = material;
					val4.defaultMaterialAddress = new AssetReferenceT<Material>("");
					SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
					val5.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val4 };
					List<MeshReplacement> list2 = new List<MeshReplacement>
					{
						new MeshReplacement
						{
							renderer = (Renderer)(object)target,
							mesh = mesh,
							meshAddress = new AssetReferenceT<Mesh>("")
						}
					};
					foreach (SkinnedMeshRenderer item in renderers.Where((SkinnedMeshRenderer r) => ((Object)r).name == "BowMesh" || ((Object)r).name == "HuntressScarfMesh"))
					{
						Mesh val6 = new Mesh
						{
							name = "EclipseHuntressNewSkins_hidden_" + ((Object)item).name
						};
						val6.vertices = (Vector3[])(object)new Vector3[0];
						val6.triangles = new int[0];
						list2.Add(new MeshReplacement
						{
							renderer = (Renderer)(object)item,
							mesh = val6,
							meshAddress = new AssetReferenceT<Mesh>("")
						});
					}
					val5.meshReplacements = list2.ToArray();
					skin = ScriptableObject.CreateInstance<SkinDef>();
					((Object)skin).name = "skinEclipseHuntressNewSkins_" + design.Slug;
					skin.nameToken = "ECLIPSE_HUNTRESS_REWORK_" + design.Slug.ToUpperInvariant().Replace('-', '_');
					LanguageAPI.Add(skin.nameToken, design.Name);
					skin.icon = CreateIcon(design.Colors);
					skin.unlockableDef = null;
					skin.rootObject = modelPrefab;
					skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
					skin.skinDefParams = val5;
					list.Add(skin);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_HUNTRESS_REWORK_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)("RODANIUS_HUNTRESS_SKIN_FAILED slug=" + design.Slug + " " + ex));
				}
			}
			if (list.Count != 0)
			{
				controller.skins = controller.skins.Concat(list).ToArray();
				AttachBoundsDriver(target);
				registered = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_HUNTRESS_REWORK_REGISTERED count=" + list.Count + " version=0.2.0"));
			}
		}

		private static Sprite CreateIcon(Color32[] colors)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
			Color32[] array = (Color32[])(object)new Color32[4096];
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					int num = ((i > j) ? ((i <= 63 - j) ? 1 : 0) : ((i > 63 - j) ? 2 : 3));
					array[i * 64 + j] = (Color32)((j < 2 || j > 61 || i < 2 || i > 61 || Math.Abs(i - j) < 2 || Math.Abs(i - (63 - j)) < 2) ? new Color32((byte)48, (byte)48, (byte)48, byte.MaxValue) : colors[num]);
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			return Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f));
		}

		private void CheckLoadDeadline(string asset)
		{
			if (Time.realtimeSinceStartup > registrationDeadline)
			{
				throw new TimeoutException("Stopped loading " + asset + "; continuing startup without the skin.");
			}
		}

		private void SyncDisplaySkins()
		{
			if (!registered)
			{
				return;
			}
			SurvivorDef val = SurvivorCatalog.allSurvivorDefs.FirstOrDefault((Func<SurvivorDef, bool>)((SurvivorDef s) => Object.op_Implicit((Object)(object)s) && Object.op_Implicit((Object)(object)s.bodyPrefab) && ((Object)s.bodyPrefab).name == "HuntressBody"));
			if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.displayPrefab))
			{
				return;
			}
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (!Object.op_Implicit((Object)(object)componentInChildren))
			{
				return;
			}
			HuntressMaterialProbe.Attach(((IEnumerable<SkinnedMeshRenderer>)((Component)(object)componentInChildren).GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => ((Object)r).name == "HuntressMesh")));
			ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
			SkinDef[] bodySkins = modelPrefab.GetComponent<ModelSkinController>().skins;
			SkinDef[] second = (val2.skins ?? Array.Empty<SkinDef>()).Where((SkinDef s) => Object.op_Implicit((Object)(object)s) && !bodySkins.Any((SkinDef b) => (Object)(object)b == (Object)(object)s || (Object.op_Implicit((Object)(object)b) && ((Object)b).name == ((Object)s).name))).ToArray();
			val2.skins = bodySkins.Concat(second).ToArray();
			SkinnedMeshRenderer val3 = ((IEnumerable<SkinnedMeshRenderer>)((Component)(object)componentInChildren).GetSkinRenderers<SkinnedMeshRenderer>(inactive: true, (SkinDefParams)null)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => ((Object)r).name == "HuntressMesh"));
			if (Object.op_Implicit((Object)(object)val3))
			{
				AttachBoundsDriver(val3);
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_HUNTRESS_REWORK_DISPLAY_READY skins=" + val2.skins.Length));
		}

		private static void AttachBoundsDriver(SkinnedMeshRenderer target)
		{
			if (!Object.op_Implicit((Object)(object)((Component)target).GetComponent<NewHuntressSkinBounds>()))
			{
				((Component)target).gameObject.AddComponent<NewHuntressSkinBounds>();
			}
		}

		private Texture2D ReadTexture(string name, bool linear)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_004b: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, linear)
			{
				name = name,
				anisoLevel = 4,
				filterMode = (FilterMode)2
			};
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(Path.Combine(folder, name)), false))
			{
				throw new InvalidDataException("Cannot decode " + name);
			}
			return val;
		}

		private Mesh ReadMesh(string path, SkinnedMeshRenderer renderer, Mesh reference)
		{
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0341: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			//IL_036b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_038f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0397: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			using BinaryReader binaryReader = new BinaryReader(File.OpenRead(path));
			if (new string(binaryReader.ReadChars(4)) != "HEP1")
			{
				throw new InvalidDataException("Invalid mesh signature.");
			}
			int num = binaryReader.ReadInt32();
			int num2 = binaryReader.ReadInt32();
			int num3 = binaryReader.ReadInt32();
			if (num < 3 || num > 200000 || num2 < 3 || num2 > 1200000 || num2 % 3 != 0 || num3 != 69)
			{
				throw new InvalidDataException("Invalid mesh dimensions.");
			}
			int[] array = new int[num3];
			for (int i = 0; i < num3; i++)
			{
				int num4 = binaryReader.ReadInt32();
				if (num4 < 1 || num4 > 128)
				{
					throw new InvalidDataException("Invalid bone name.");
				}
				string name = Encoding.UTF8.GetString(binaryReader.ReadBytes(num4));
				array[i] = Array.FindIndex(renderer.bones, (Transform t) => Object.op_Implicit((Object)(object)t) && ((Object)t).name == name);
				if (array[i] < 0)
				{
					throw new InvalidDataException("Missing reference bone: " + name);
				}
			}
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector3[] array3 = (Vector3[])(object)new Vector3[num];
			Vector2[] array4 = (Vector2[])(object)new Vector2[num];
			BoneWeight[] array5 = (BoneWeight[])(object)new BoneWeight[num];
			for (int num5 = 0; num5 < num; num5++)
			{
				array2[num5] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array3[num5] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
				array4[num5] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
				int[] array6 = new int[4];
				for (int num6 = 0; num6 < 4; num6++)
				{
					int num7 = binaryReader.ReadInt32();
					if (num7 < 0 || num7 >= num3)
					{
						throw new InvalidDataException("Bone out of range.");
					}
					array6[num6] = array[num7];
				}
				float[] array7 = new float[4];
				for (int num8 = 0; num8 < 4; num8++)
				{
					array7[num8] = binaryReader.ReadSingle();
				}
				if (array7.Any((float n) => float.IsNaN(n) || float.IsInfinity(n) || n < 0f) || Math.Abs(array7.Sum() - 1f) > 0.002f)
				{
					throw new InvalidDataException("Invalid skin weight.");
				}
				if (!Finite(array2[num5]) || !Finite(array3[num5]))
				{
					throw new InvalidDataException("Non-finite vertex.");
				}
				int num9 = num5;
				BoneWeight val = default(BoneWeight);
				((BoneWeight)(ref val)).boneIndex0 = array6[0];
				((BoneWeight)(ref val)).boneIndex1 = array6[1];
				((BoneWeight)(ref val)).boneIndex2 = array6[2];
				((BoneWeight)(ref val)).boneIndex3 = array6[3];
				((BoneWeight)(ref val)).weight0 = array7[0];
				((BoneWeight)(ref val)).weight1 = array7[1];
				((BoneWeight)(ref val)).weight2 = array7[2];
				((BoneWeight)(ref val)).weight3 = array7[3];
				array5[num9] = val;
			}
			int[] array8 = new int[num2];
			for (int num10 = 0; num10 < num2; num10++)
			{
				array8[num10] = binaryReader.ReadInt32();
				if (array8[num10] < 0 || array8[num10] >= num)
				{
					throw new InvalidDataException("Triangle out of range.");
				}
			}
			if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
			{
				throw new InvalidDataException("Unexpected trailing mesh data.");
			}
			Mesh val2 = new Mesh
			{
				name = "EclipseHuntressAuthoredMesh",
				indexFormat = (IndexFormat)(num > 65535),
				vertices = array2,
				normals = array3,
				uv = array4,
				boneWeights = array5,
				bindposes = reference.bindposes,
				triangles = array8
			};
			val2.RecalculateBounds();
			val2.RecalculateTangents();
			return val2;
		}

		private static bool Finite(Vector3 v)
		{
			//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: 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)
			if (!float.IsNaN(v.x + v.y + v.z))
			{
				return !float.IsInfinity(v.x + v.y + v.z);
			}
			return false;
		}
	}
	public sealed class NewHuntressSkinBounds : MonoBehaviour
	{
		private SkinnedMeshRenderer target;

		private Bounds original;

		private bool applied;

		private Mesh boundedMesh;

		private void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			target = ((Component)this).GetComponent<SkinnedMeshRenderer>();
			if (Object.op_Implicit((Object)(object)target))
			{
				original = ((Renderer)target).localBounds;
			}
		}

		private void LateUpdate()
		{
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)target))
			{
				return;
			}
			bool flag = Object.op_Implicit((Object)(object)target.sharedMesh) && ((Object)target.sharedMesh).name.StartsWith("EclipseHuntressNewSkins_", StringComparison.Ordinal);
			if (flag && (!applied || (Object)(object)boundedMesh != (Object)(object)target.sharedMesh))
			{
				if (!applied)
				{
					original = ((Renderer)target).localBounds;
				}
				Bounds localBounds = default(Bounds);
				((Bounds)(ref localBounds))..ctor(new Vector3(0f, 0f, 0.3f), new Vector3(6.5f, 6.5f, 6.5f));
				((Bounds)(ref localBounds)).Encapsulate(target.sharedMesh.bounds);
				((Renderer)target).localBounds = localBounds;
				applied = true;
				boundedMesh = target.sharedMesh;
			}
			else if (!flag && applied)
			{
				((Renderer)target).localBounds = original;
				applied = false;
				boundedMesh = null;
			}
		}

		private void OnDisable()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target) && applied)
			{
				((Renderer)target).localBounds = original;
			}
			applied = false;
			boundedMesh = null;
		}
	}
}
namespace Rodanius.Standalone
{
	public static class CatalogueSpecs
	{
		public static bool Matches(SkinRecord r)
		{
			switch (r.key)
			{
			case "acrid-bog-hopper":
				if (r.skinId == "EclipsePlaytestAcridE1BogHopper" && r.family == "single" && r.name == "Bog Hopper" && r.survivor == "Acrid")
				{
					return r.tier == 1;
				}
				return false;
			case "acrid-duck-and-cover":
				if (r.skinId == "EclipsePlaytestAcridE2DuckAndCover" && r.family == "single" && r.name == "Duck and Cover" && r.survivor == "Acrid")
				{
					return r.tier == 2;
				}
				return false;
			case "acrid-trash-panda":
				if (r.skinId == "EclipsePlaytestAcridE3TrashPanda" && r.family == "single" && r.name == "Trash Panda" && r.survivor == "Acrid")
				{
					return r.tier == 3;
				}
				return false;
			case "acrid-good-boy":
				if (r.skinId == "EclipsePlaytestAcridE4GoodBoy" && r.family == "single" && r.name == "Good Boy" && r.survivor == "Acrid")
				{
					return r.tier == 4;
				}
				return false;
			case "acrid-ginger-cat":
				if (r.skinId == "EclipsePlaytestAcridE5GingerCat" && r.family == "single" && r.name == "Ginger Cat" && r.survivor == "Acrid")
				{
					return r.tier == 5;
				}
				return false;
			case "acrid-squirrel":
				if (r.skinId == "EclipsePlaytestAcridE6Squirrel" && r.family == "single" && r.name == "Squirrel" && r.survivor == "Acrid")
				{
					return r.tier == 6;
				}
				return false;
			case "acrid-goat":
				if (r.skinId == "EclipsePlaytestAcridE7Goat" && r.family == "single" && r.name == "Goat" && r.survivor == "Acrid")
				{
					return r.tier == 7;
				}
				return false;
			case "acrid-abyssal-angler":
				if (r.skinId == "EclipsePlaytestAcridE8AbyssalAngler" && r.family == "single" && r.name == "Abyssal Angler" && r.survivor == "Acrid")
				{
					return r.tier == 8;
				}
				return false;
			case "bandit-corner-crew":
				if (r.skinId == "skinEclipsePlaytestBanditE1" && r.family == "single" && r.name == "Corner Crew" && r.survivor == "Bandit")
				{
					return r.tier == 1;
				}
				return false;
			case "bandit-after-hours":
				if (r.skinId == "skinEclipsePlaytestBanditE2" && r.family == "single" && r.name == "After Hours" && r.survivor == "Bandit")
				{
					return r.tier == 2;
				}
				return false;
			case "bandit-house-always-wins":
				if (r.skinId == "skinEclipsePlaytestBanditE3" && r.family == "single" && r.name == "House Always Wins" && r.survivor == "Bandit")
				{
					return r.tier == 3;
				}
				return false;
			case "bandit-card-shark":
				if (r.skinId == "skinEclipsePlaytestBanditE5" && r.family == "single" && r.name == "Card Shark" && r.survivor == "Bandit")
				{
					return r.tier == 5;
				}
				return false;
			case "chef-crab-rangoon":
				if (r.skinId == "EclipsePlaytestChefE2CrabRangoon" && r.family == "single" && r.name == "Crab Rangoon" && r.survivor == "CHEF")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-frontier-recruit":
				if (r.skinId == "skinEclipsePlaytestCommandoE1" && r.family == "single" && r.name == "Frontier Recruit" && r.survivor == "Commando")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-vacuum-breacher":
				if (r.skinId == "skinEclipsePlaytestCommandoE2" && r.family == "single" && r.name == "Vacuum Breacher" && r.survivor == "Commando")
				{
					return r.tier == 2;
				}
				return false;
			case "commando-expedition-marshal":
				if (r.skinId == "skinEclipsePlaytestCommandoE3" && r.family == "single" && r.name == "Expedition Marshal" && r.survivor == "Commando")
				{
					return r.tier == 3;
				}
				return false;
			case "commando-clockwork-infantry":
				if (r.skinId == "skinEclipsePlaytestCommandoE4" && r.family == "single" && r.name == "Clockwork Infantry" && r.survivor == "Commando")
				{
					return r.tier == 4;
				}
				return false;
			case "commando-action-figure":
				if (r.skinId == "skinEclipsePlaytestCommandoE5" && r.family == "single" && r.name == "Action Figure" && r.survivor == "Commando")
				{
					return r.tier == 5;
				}
				return false;
			case "commando-quartermaster":
				if (r.skinId == "skinEclipsePlaytestCommandoE6" && r.family == "single" && r.name == "Quartermaster" && r.survivor == "Commando")
				{
					return r.tier == 6;
				}
				return false;
			case "commando-one-man-band":
				if (r.skinId == "skinEclipsePlaytestCommandoE7" && r.family == "single" && r.name == "One-Man Band" && r.survivor == "Commando")
				{
					return r.tier == 7;
				}
				return false;
			case "commando-extinction-protocol":
				if (r.skinId == "skinEclipsePlaytestCommandoE8" && r.family == "single" && r.name == "Extinction Protocol" && r.survivor == "Commando")
				{
					return r.tier == 8;
				}
				return false;
			case "drifter-happy-camper":
				if (r.skinId == "EclipsePlaytestDrifterE1HappyCamper" && r.family == "single" && r.name == "Happy Camper" && r.survivor == "Drifter")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-union-builder":
				if (r.skinId == "skinEclipsePlaytestEngineerE1_union-builder" && r.family == "single" && r.name == "Union Builder" && r.survivor == "Engineer")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-mine-surveyor":
				if (r.skinId == "skinEclipsePlaytestEngineerE2_mine-surveyor" && r.family == "single" && r.name == "Mine Surveyor" && r.survivor == "Engineer")
				{
					return r.tier == 2;
				}
				return false;
			case "false-son-penguin":
				if (r.skinId == "EclipsePlaytestFalseSonE3Penguin" && r.family == "single" && r.name == "Penguin" && r.survivor == "False Son")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-hare-trigger":
				if (r.skinId == "skinEclipseHuntressNewSkins_hare-trigger" && r.family == "huntress" && r.name == "Hare Trigger" && r.survivor == "Huntress")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-pink-slip":
				if (r.skinId == "skinEclipseHuntressNewSkins_pink-slip" && r.family == "huntress" && r.name == "Pink Slip" && r.survivor == "Huntress")
				{
					return r.tier == 2;
				}
				return false;
			case "huntress-wallflower":
				if (r.skinId == "skinEclipseHuntressNewSkins_wallflower" && r.family == "huntress" && r.name == "Wallflower" && r.survivor == "Huntress")
				{
					return r.tier == 3;
				}
				return false;
			case "huntress-shell-shock":
				if (r.skinId == "skinEclipseHuntressNewSkins_shell-shock" && r.family == "huntress" && r.name == "Shell Shock" && r.survivor == "Huntress")
				{
					return r.tier == 4;
				}
				return false;
			case "huntress-hot-pursuit":
				if (r.skinId == "skinEclipseHuntressNewSkins_hot-pursuit" && r.family == "huntress" && r.name == "Hot Pursuit" && r.survivor == "Huntress")
				{
					return r.tier == 5;
				}
				return false;
			case "huntress-banana":
				if (r.skinId == "skinHuntressLiquidAssetsPlaytest_liquid-assets" && r.family == "single" && r.name == "Banana" && r.survivor == "Huntress")
				{
					return r.tier == 6;
				}
				return false;
			case "huntress-loose-ends":
				if (r.skinId == "skinEclipseHuntressNewSkins_loose-ends" && r.family == "huntress" && r.name == "Loose Ends" && r.survivor == "Huntress")
				{
					return r.tier == 7;
				}
				return false;
			case "huntress-dawnstrider":
				if (r.skinId == "skinEclipseHuntressNewSkins_dawnstrider" && r.family == "huntress" && r.name == "Dawnstrider" && r.survivor == "Huntress")
				{
					return r.tier == 8;
				}
				return false;
			case "loader-go-fetch":
				if (r.skinId == "EclipseLoaderE1" && r.family == "loader" && r.name == "Go Fetch" && r.survivor == "Loader")
				{
					return r.tier == 1;
				}
				return false;
			case "loader-bear-knuckle":
				if (r.skinId == "EclipseLoaderE2" && r.family == "loader" && r.name == "Bear Knuckle" && r.survivor == "Loader")
				{
					return r.tier == 2;
				}
				return false;
			case "loader-knuckle-dragger":
				if (r.skinId == "EclipseLoaderE3" && r.family == "loader" && r.name == "Knuckle Dragger" && r.survivor == "Loader")
				{
					return r.tier == 3;
				}
				return false;
			case "loader-brick-house":
				if (r.skinId == "EclipseLoaderE4" && r.family == "loader" && r.name == "Brick House" && r.survivor == "Loader")
				{
					return r.tier == 4;
				}
				return false;
			case "loader-dead-weight":
				if (r.skinId == "EclipseLoaderE5" && r.family == "loader" && r.name == "Dead Weight" && r.survivor == "Loader")
				{
					return r.tier == 5;
				}
				return false;
			case "loader-rubber-bandit":
				if (r.skinId == "EclipseLoaderE6" && r.family == "loader" && r.name == "Rubber Bandit" && r.survivor == "Loader")
				{
					return r.tier == 6;
				}
				return false;
			case "loader-high-five":
				if (r.skinId == "EclipseLoaderE7" && r.family == "loader" && r.name == "High Five" && r.survivor == "Loader")
				{
					return r.tier == 7;
				}
				return false;
			case "loader-titan-champion":
				if (r.skinId == "EclipseLoaderE8" && r.family == "loader" && r.name == "Titan Champion" && r.survivor == "Loader")
				{
					return r.tier == 8;
				}
				return false;
			case "mul-t-yard-salvager":
				if (r.skinId == "skinEclipsePlaytest_MULT_E1" && r.family == "single" && r.name == "Yard Salvager" && r.survivor == "MUL-T")
				{
					return r.tier == 1;
				}
				return false;
			case "mul-t-timber-hauler":
				if (r.skinId == "skinEclipsePlaytest_MULT_E2" && r.family == "single" && r.name == "Timber Hauler" && r.survivor == "MUL-T")
				{
					return r.tier == 2;
				}
				return false;
			case "mul-t-deep-salvage-unit":
				if (r.skinId == "skinEclipsePlaytest_MULT_E3" && r.family == "single" && r.name == "Deep-Salvage Unit" && r.survivor == "MUL-T")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-roadworn-ronin":
				if (r.skinId == "EclipsePlaytestMercenaryE1RoadwornRonin" && r.family == "single" && r.name == "Roadworn Ronin" && r.survivor == "Mercenary")
				{
					return r.tier == 1;
				}
				return false;
			case "mercenary-canopy-cutter":
				if (r.skinId == "EclipsePlaytestMercenaryE3CanopyCutter" && r.family == "single" && r.name == "Canopy Cutter" && r.survivor == "Mercenary")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-circuit-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE2CircuitDuelist" && r.family == "single" && r.name == "Circuit Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 2;
				}
				return false;
			case "mercenary-deli-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE7DeliDuelist" && r.family == "single" && r.name == "Deli Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 7;
				}
				return false;
			case "rex-prickly-customer":
				if (r.skinId == "skinEclipseRexPricklyCustomer" && r.family == "single" && r.name == "Prickly Customer" && r.survivor == "REX")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-hole-in-one":
				if (r.skinId == "EclipseRailgunnerE1" && r.family == "railgunner" && r.name == "Hole in One" && r.survivor == "Railgunner")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-night-sight":
				if (r.skinId == "EclipseRailgunnerE2" && r.family == "railgunner" && r.name == "Night Sight" && r.survivor == "Railgunner")
				{
					return r.tier == 2;
				}
				return false;
			case "railgunner-ring-leader":
				if (r.skinId == "EclipseRailgunnerE3" && r.family == "railgunner" && r.name == "Ring Leader" && r.survivor == "Railgunner")
				{
					return r.tier == 3;
				}
				return false;
			case "railgunner-fire-away":
				if (r.skinId == "EclipseRailgunnerE4" && r.family == "railgunner" && r.name == "Fire Away" && r.survivor == "Railgunner")
				{
					return r.tier == 4;
				}
				return false;
			case "railgunner-point-taken":
				if (r.skinId == "EclipseRailgunnerE5" && r.family == "railgunner" && r.name == "Point Taken" && r.survivor == "Railgunner")
				{
					return r.tier == 5;
				}
				return false;
			case "railgunner-express-delivery":
				if (r.skinId == "EclipseRailgunnerE6" && r.family == "railgunner" && r.name == "Express Delivery" && r.survivor == "Railgunner")
				{
					return r.tier == 6;
				}
				return false;
			case "railgunner-last-straw":
				if (r.skinId == "EclipseRailgunnerE7" && r.family == "railgunner" && r.name == "Last Straw" && r.survivor == "Railgunner")
				{
					return r.tier == 7;
				}
				return false;
			case "railgunner-horizon-lancer":
				if (r.skinId == "EclipseRailgunnerE8" && r.family == "railgunner" && r.name == "Horizon Lancer" && r.survivor == "Railgunner")
				{
					return r.tier == 8;
				}
				return false;
			case "seeker-breaditation":
				if (r.skinId == "EclipsePlaytestSeekerE7Breaditation" && r.family == "single" && r.name == "Breaditation" && r.survivor == "Seeker")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-desert-castaway":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE1" && r.family == "single" && r.name == "Desert Castaway" && r.survivor == "Void Fiend")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-live-wire":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE2" && r.family == "single" && r.name == "Live Wire" && r.survivor == "Void Fiend")
				{
					return r.tier == 2;
				}
				return false;
			case "void-fiend-pressure-guest":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE3" && r.family == "single" && r.name == "Pressure Guest" && r.survivor == "Void Fiend")
				{
					return r.tier == 3;
				}
				return false;
			case "void-fiend-orange-you-glad":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE4" && r.family == "single" && r.name == "Orange You Glad" && r.survivor == "Void Fiend")
				{
					return r.tier == 4;
				}
				return false;
			case "void-fiend-burnt-offering":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE5" && r.family == "single" && r.name == "Burnt Offering" && r.survivor == "Void Fiend")
				{
					return r.tier == 5;
				}
				return false;
			case "void-fiend-public-information":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE6" && r.family == "single" && r.name == "Public Information" && r.survivor == "Void Fiend")
				{
					return r.tier == 6;
				}
				return false;
			case "void-fiend-surprise-inside":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE7" && r.family == "single" && r.name == "Surprise Inside" && r.survivor == "Void Fiend")
				{
					return r.tier == 7;
				}
				return false;
			case "void-fiend-containment-impossible":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE8" && r.family == "single" && r.name == "Containment Impossible" && r.survivor == "Void Fiend")
				{
					return r.tier == 8;
				}
				return false;
			default:
				return false;
			}
		}
	}
	[Serializable]
	public sealed class AssetFile
	{
		public string path;

		public string sha256;
	}
	[Serializable]
	public sealed class SkinRecord
	{
		public int schema;

		public int tier;

		public string key;

		public string name;

		public string survivor;

		public string family;

		public string skinId;

		public string assetDirectory;

		public string icon;

		public string iconSha256;

		public AssetFile[] files;

		[NonSerialized]
		public string Root;

		public string AssetRoot => SkinDiscovery.SafePath(Root, assetDirectory);
	}
	public static class SkinDiscovery
	{
		public static string SafePath(string root, string relative)
		{
			if (string.IsNullOrEmpty(relative) || Path.IsPathRooted(relative) || relative.Split('/', '\\').Any((string x) => x == ".." || x == ""))
			{
				throw new InvalidDataException("Invalid package-relative path");
			}
			string text = Path.GetFullPath(root).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
			string fullPath = Path.GetFullPath(Path.Combine(root, relative));
			if (!fullPath.StartsWith(text, StringComparison.OrdinalIgnoreCase) && fullPath != text.TrimEnd(Path.DirectorySeparatorChar))
			{
				throw new InvalidDataException("Package path escaped root");
			}
			return fullPath;
		}

		private static IEnumerable<string> FindRecords(string root, Action<string> log)
		{
			Stack<string> todo = new Stack<string>();
			todo.Push(root);
			while (todo.Count > 0)
			{
				string dir = todo.Pop();
				string text = Path.Combine(dir, "rodanius-skin.json");
				if (File.Exists(text))
				{
					yield return text;
				}
				string[] directories;
				try
				{
					directories = Directory.GetDirectories(dir);
				}
				catch (Exception ex)
				{
					log("RODANIUS_DISCOVERY_SKIPPED " + dir + " " + ex.Message);
					continue;
				}
				string[] array = directories;
				foreach (string text2 in array)
				{
					try
					{
						if ((File.GetAttributes(text2) & FileAttributes.ReparsePoint) == 0)
						{
							todo.Push(text2);
						}
					}
					catch (Exception ex2)
					{
						log("RODANIUS_DISCOVERY_SKIPPED " + ex2.Message);
					}
				}
			}
		}

		public static string Hash(string path)
		{
			using FileStream inputStream = File.OpenRead(path);
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant();
		}

		public static List<SkinRecord> Load(string family, Action<string> log, bool verifyAssets = true)
		{
			List<SkinRecord> list = new List<SkinRecord>();
			foreach (string item in FindRecords(Paths.PluginPath, log))
			{
				try
				{
					if (new FileInfo(item).Length > 262144)
					{
						throw new InvalidDataException("Manifest too large");
					}
					SkinRecord skinRecord = JsonUtility.FromJson<SkinRecord>(File.ReadAllText(item));
					if (skinRecord == null || skinRecord.schema != 1 || !CatalogueSpecs.Matches(skinRecord))
					{
						throw new InvalidDataException("Unknown standalone skin identity");
					}
					if (family != null && skinRecord.family != family)
					{
						continue;
					}
					skinRecord.Root = Path.GetDirectoryName(item);
					SafePath(skinRecord.Root, skinRecord.assetDirectory);
					SafePath(skinRecord.Root, skinRecord.icon);
					if (verifyAssets)
					{
						if (skinRecord.files == null || skinRecord.files.Length == 0 || skinRecord.files.Length > 100)
						{
							throw new InvalidDataException("Asset inventory missing");
						}
						AssetFile[] files = skinRecord.files;
						foreach (AssetFile assetFile in files)
						{
							if (assetFile == null || assetFile.sha256 == null || assetFile.sha256.Length != 64 || Hash(SafePath(skinRecord.Root, assetFile.path)) != assetFile.sha256)
							{
								throw new InvalidDataException("Asset hash mismatch: " + ((assetFile == null) ? "null" : assetFile.path));
							}
						}
					}
					list.Add(skinRecord);
				}
				catch (Exception ex)
				{
					log("RODANIUS_SKIN_PACKAGE_REJECTED file=" + item + " error=" + ex.Message);
				}
			}
			List<SkinRecord> list2 = new List<SkinRecord>();
			foreach (IGrouping<string, SkinRecord> item2 in list.GroupBy<SkinRecord, string>((SkinRecord r) => r.skinId, StringComparer.Ordinal))
			{
				if (item2.Count() != 1)
				{
					log("RODANIUS_DUPLICATE_SKIN_PACKAGE id=" + item2.Key + " paths=" + string.Join(";", item2.Select((SkinRecord r) => r.Root)));
				}
				else
				{
					list2.Add(item2.Single());
				}
			}
			return list2.OrderBy<SkinRecord, string>((SkinRecord r) => r.survivor, StringComparer.Ordinal).ThenBy((SkinRecord r) => r.tier).ToList();
		}
	}
}

BepInEx/plugins/RodaniusSkinRuntime/Rodanius.SkinPresentation.dll

Decompiled a day 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.Security.Cryptography;
using BepInEx;
using HG.Reflection;
using R2API;
using RoR2;
using RoR2.UI.MainMenu;
using Rodanius.Standalone;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: OptIn]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Rodanius.SkinPresentation
{
	[BepInPlugin("rodanius.skinpresentation", "Rodanius Skin Presentation", "0.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Presentation : BaseUnityPlugin
	{
		private static Presentation instance;

		private readonly Dictionary<string, Sprite> portraits = new Dictionary<string, Sprite>(StringComparer.Ordinal);

		private readonly Dictionary<string, string> names = new Dictionary<string, string>(StringComparer.Ordinal);

		private readonly HashSet<string> reported = new HashSet<string>(StringComparer.Ordinal);

		private readonly HashSet<string> missing = new HashSet<string>(StringComparer.Ordinal);

		private bool loaded;

		private void Awake()
		{
			instance = this;
			RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(Apply));
			MainMenuController.OnMainMenuInitialised += Apply;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("RODANIUS_PRESENTATION_LOCATION " + ((BaseUnityPlugin)this).Info.Location));
		}

		[SystemInitializer(new Type[] { typeof(SkinCatalog) })]
		private static void Initialize()
		{
			if (Object.op_Implicit((Object)(object)instance))
			{
				instance.Apply();
			}
		}

		private void Load()
		{
			//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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			if (loaded)
			{
				return;
			}
			loaded = true;
			foreach (SkinRecord item in SkinDiscovery.Load(null, delegate(string s)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)s);
			}, verifyAssets: false))
			{
				try
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)("RODANIUS_SKIN_PACKAGE_FOUND id=" + item.skinId + " path=" + item.Root));
					string text = SkinDiscovery.SafePath(item.Root, item.icon);
					if (new FileInfo(text).Length > 4194304 || item.iconSha256 == null || SkinDiscovery.Hash(text) != item.iconSha256)
					{
						throw new InvalidDataException("Portrait hash/size mismatch");
					}
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false, false)
					{
						name = "Rodanius_" + item.key,
						filterMode = (FilterMode)1,
						wrapMode = (TextureWrapMode)1
					};
					try
					{
						if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text), false) || ((Texture)val).width != 256 || ((Texture)val).height != 256)
						{
							throw new InvalidDataException("Expected 256px portrait");
						}
						portraits.Add(item.skinId, Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f)));
						names.Add(item.skinId, item.name);
					}
					catch
					{
						Object.Destroy((Object)(object)val);
						throw;
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("RODANIUS_PORTRAIT_REJECTED key=" + item.key + " error=" + ex.Message));
				}
			}
		}

		private void Apply()
		{
			try
			{
				Load();
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				for (int i = 0; i < SkinCatalog.skinCount; i++)
				{
					SkinDef skinDef = SkinCatalog.GetSkinDef((SkinIndex)i);
					if (Object.op_Implicit((Object)(object)skinDef) && portraits.TryGetValue(((Object)skinDef).name, out var value))
					{
						hashSet.Add(((Object)skinDef).name);
						skinDef.icon = value;
						if (reported.Add(((Object)skinDef).name))
						{
							LanguageAPI.Add(skinDef.nameToken, names[((Object)skinDef).name]);
							((BaseUnityPlugin)this).Logger.LogInfo((object)("RODANIUS_PORTRAIT_APPLIED " + ((Object)skinDef).name));
						}
					}
				}
				foreach (string key in portraits.Keys)
				{
					if (!hashSet.Contains(key) && missing.Add(key))
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("RODANIUS_SKIN_NOT_REGISTERED id=" + key + " packagePresent=true; inspect this skin's registration error and duplicate plugin locations."));
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("RODANIUS_PORTRAIT_UPDATE_FAILED " + ex));
			}
		}

		private void OnDestroy()
		{
			RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(Apply));
			MainMenuController.OnMainMenuInitialised -= Apply;
			if ((Object)(object)instance == (Object)(object)this)
			{
				instance = null;
			}
		}
	}
}
namespace Rodanius.Standalone
{
	public static class CatalogueSpecs
	{
		public static bool Matches(SkinRecord r)
		{
			switch (r.key)
			{
			case "acrid-bog-hopper":
				if (r.skinId == "EclipsePlaytestAcridE1BogHopper" && r.family == "single" && r.name == "Bog Hopper" && r.survivor == "Acrid")
				{
					return r.tier == 1;
				}
				return false;
			case "acrid-duck-and-cover":
				if (r.skinId == "EclipsePlaytestAcridE2DuckAndCover" && r.family == "single" && r.name == "Duck and Cover" && r.survivor == "Acrid")
				{
					return r.tier == 2;
				}
				return false;
			case "acrid-trash-panda":
				if (r.skinId == "EclipsePlaytestAcridE3TrashPanda" && r.family == "single" && r.name == "Trash Panda" && r.survivor == "Acrid")
				{
					return r.tier == 3;
				}
				return false;
			case "acrid-good-boy":
				if (r.skinId == "EclipsePlaytestAcridE4GoodBoy" && r.family == "single" && r.name == "Good Boy" && r.survivor == "Acrid")
				{
					return r.tier == 4;
				}
				return false;
			case "acrid-ginger-cat":
				if (r.skinId == "EclipsePlaytestAcridE5GingerCat" && r.family == "single" && r.name == "Ginger Cat" && r.survivor == "Acrid")
				{
					return r.tier == 5;
				}
				return false;
			case "acrid-squirrel":
				if (r.skinId == "EclipsePlaytestAcridE6Squirrel" && r.family == "single" && r.name == "Squirrel" && r.survivor == "Acrid")
				{
					return r.tier == 6;
				}
				return false;
			case "acrid-goat":
				if (r.skinId == "EclipsePlaytestAcridE7Goat" && r.family == "single" && r.name == "Goat" && r.survivor == "Acrid")
				{
					return r.tier == 7;
				}
				return false;
			case "acrid-abyssal-angler":
				if (r.skinId == "EclipsePlaytestAcridE8AbyssalAngler" && r.family == "single" && r.name == "Abyssal Angler" && r.survivor == "Acrid")
				{
					return r.tier == 8;
				}
				return false;
			case "bandit-corner-crew":
				if (r.skinId == "skinEclipsePlaytestBanditE1" && r.family == "single" && r.name == "Corner Crew" && r.survivor == "Bandit")
				{
					return r.tier == 1;
				}
				return false;
			case "bandit-after-hours":
				if (r.skinId == "skinEclipsePlaytestBanditE2" && r.family == "single" && r.name == "After Hours" && r.survivor == "Bandit")
				{
					return r.tier == 2;
				}
				return false;
			case "bandit-house-always-wins":
				if (r.skinId == "skinEclipsePlaytestBanditE3" && r.family == "single" && r.name == "House Always Wins" && r.survivor == "Bandit")
				{
					return r.tier == 3;
				}
				return false;
			case "bandit-card-shark":
				if (r.skinId == "skinEclipsePlaytestBanditE5" && r.family == "single" && r.name == "Card Shark" && r.survivor == "Bandit")
				{
					return r.tier == 5;
				}
				return false;
			case "chef-crab-rangoon":
				if (r.skinId == "EclipsePlaytestChefE2CrabRangoon" && r.family == "single" && r.name == "Crab Rangoon" && r.survivor == "CHEF")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-frontier-recruit":
				if (r.skinId == "skinEclipsePlaytestCommandoE1" && r.family == "single" && r.name == "Frontier Recruit" && r.survivor == "Commando")
				{
					return r.tier == 1;
				}
				return false;
			case "commando-vacuum-breacher":
				if (r.skinId == "skinEclipsePlaytestCommandoE2" && r.family == "single" && r.name == "Vacuum Breacher" && r.survivor == "Commando")
				{
					return r.tier == 2;
				}
				return false;
			case "commando-expedition-marshal":
				if (r.skinId == "skinEclipsePlaytestCommandoE3" && r.family == "single" && r.name == "Expedition Marshal" && r.survivor == "Commando")
				{
					return r.tier == 3;
				}
				return false;
			case "commando-clockwork-infantry":
				if (r.skinId == "skinEclipsePlaytestCommandoE4" && r.family == "single" && r.name == "Clockwork Infantry" && r.survivor == "Commando")
				{
					return r.tier == 4;
				}
				return false;
			case "commando-action-figure":
				if (r.skinId == "skinEclipsePlaytestCommandoE5" && r.family == "single" && r.name == "Action Figure" && r.survivor == "Commando")
				{
					return r.tier == 5;
				}
				return false;
			case "commando-quartermaster":
				if (r.skinId == "skinEclipsePlaytestCommandoE6" && r.family == "single" && r.name == "Quartermaster" && r.survivor == "Commando")
				{
					return r.tier == 6;
				}
				return false;
			case "commando-one-man-band":
				if (r.skinId == "skinEclipsePlaytestCommandoE7" && r.family == "single" && r.name == "One-Man Band" && r.survivor == "Commando")
				{
					return r.tier == 7;
				}
				return false;
			case "commando-extinction-protocol":
				if (r.skinId == "skinEclipsePlaytestCommandoE8" && r.family == "single" && r.name == "Extinction Protocol" && r.survivor == "Commando")
				{
					return r.tier == 8;
				}
				return false;
			case "drifter-happy-camper":
				if (r.skinId == "EclipsePlaytestDrifterE1HappyCamper" && r.family == "single" && r.name == "Happy Camper" && r.survivor == "Drifter")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-union-builder":
				if (r.skinId == "skinEclipsePlaytestEngineerE1_union-builder" && r.family == "single" && r.name == "Union Builder" && r.survivor == "Engineer")
				{
					return r.tier == 1;
				}
				return false;
			case "engineer-mine-surveyor":
				if (r.skinId == "skinEclipsePlaytestEngineerE2_mine-surveyor" && r.family == "single" && r.name == "Mine Surveyor" && r.survivor == "Engineer")
				{
					return r.tier == 2;
				}
				return false;
			case "false-son-penguin":
				if (r.skinId == "EclipsePlaytestFalseSonE3Penguin" && r.family == "single" && r.name == "Penguin" && r.survivor == "False Son")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-hare-trigger":
				if (r.skinId == "skinEclipseHuntressNewSkins_hare-trigger" && r.family == "huntress" && r.name == "Hare Trigger" && r.survivor == "Huntress")
				{
					return r.tier == 1;
				}
				return false;
			case "huntress-pink-slip":
				if (r.skinId == "skinEclipseHuntressNewSkins_pink-slip" && r.family == "huntress" && r.name == "Pink Slip" && r.survivor == "Huntress")
				{
					return r.tier == 2;
				}
				return false;
			case "huntress-wallflower":
				if (r.skinId == "skinEclipseHuntressNewSkins_wallflower" && r.family == "huntress" && r.name == "Wallflower" && r.survivor == "Huntress")
				{
					return r.tier == 3;
				}
				return false;
			case "huntress-shell-shock":
				if (r.skinId == "skinEclipseHuntressNewSkins_shell-shock" && r.family == "huntress" && r.name == "Shell Shock" && r.survivor == "Huntress")
				{
					return r.tier == 4;
				}
				return false;
			case "huntress-hot-pursuit":
				if (r.skinId == "skinEclipseHuntressNewSkins_hot-pursuit" && r.family == "huntress" && r.name == "Hot Pursuit" && r.survivor == "Huntress")
				{
					return r.tier == 5;
				}
				return false;
			case "huntress-banana":
				if (r.skinId == "skinHuntressLiquidAssetsPlaytest_liquid-assets" && r.family == "single" && r.name == "Banana" && r.survivor == "Huntress")
				{
					return r.tier == 6;
				}
				return false;
			case "huntress-loose-ends":
				if (r.skinId == "skinEclipseHuntressNewSkins_loose-ends" && r.family == "huntress" && r.name == "Loose Ends" && r.survivor == "Huntress")
				{
					return r.tier == 7;
				}
				return false;
			case "huntress-dawnstrider":
				if (r.skinId == "skinEclipseHuntressNewSkins_dawnstrider" && r.family == "huntress" && r.name == "Dawnstrider" && r.survivor == "Huntress")
				{
					return r.tier == 8;
				}
				return false;
			case "loader-go-fetch":
				if (r.skinId == "EclipseLoaderE1" && r.family == "loader" && r.name == "Go Fetch" && r.survivor == "Loader")
				{
					return r.tier == 1;
				}
				return false;
			case "loader-bear-knuckle":
				if (r.skinId == "EclipseLoaderE2" && r.family == "loader" && r.name == "Bear Knuckle" && r.survivor == "Loader")
				{
					return r.tier == 2;
				}
				return false;
			case "loader-knuckle-dragger":
				if (r.skinId == "EclipseLoaderE3" && r.family == "loader" && r.name == "Knuckle Dragger" && r.survivor == "Loader")
				{
					return r.tier == 3;
				}
				return false;
			case "loader-brick-house":
				if (r.skinId == "EclipseLoaderE4" && r.family == "loader" && r.name == "Brick House" && r.survivor == "Loader")
				{
					return r.tier == 4;
				}
				return false;
			case "loader-dead-weight":
				if (r.skinId == "EclipseLoaderE5" && r.family == "loader" && r.name == "Dead Weight" && r.survivor == "Loader")
				{
					return r.tier == 5;
				}
				return false;
			case "loader-rubber-bandit":
				if (r.skinId == "EclipseLoaderE6" && r.family == "loader" && r.name == "Rubber Bandit" && r.survivor == "Loader")
				{
					return r.tier == 6;
				}
				return false;
			case "loader-high-five":
				if (r.skinId == "EclipseLoaderE7" && r.family == "loader" && r.name == "High Five" && r.survivor == "Loader")
				{
					return r.tier == 7;
				}
				return false;
			case "loader-titan-champion":
				if (r.skinId == "EclipseLoaderE8" && r.family == "loader" && r.name == "Titan Champion" && r.survivor == "Loader")
				{
					return r.tier == 8;
				}
				return false;
			case "mul-t-yard-salvager":
				if (r.skinId == "skinEclipsePlaytest_MULT_E1" && r.family == "single" && r.name == "Yard Salvager" && r.survivor == "MUL-T")
				{
					return r.tier == 1;
				}
				return false;
			case "mul-t-timber-hauler":
				if (r.skinId == "skinEclipsePlaytest_MULT_E2" && r.family == "single" && r.name == "Timber Hauler" && r.survivor == "MUL-T")
				{
					return r.tier == 2;
				}
				return false;
			case "mul-t-deep-salvage-unit":
				if (r.skinId == "skinEclipsePlaytest_MULT_E3" && r.family == "single" && r.name == "Deep-Salvage Unit" && r.survivor == "MUL-T")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-roadworn-ronin":
				if (r.skinId == "EclipsePlaytestMercenaryE1RoadwornRonin" && r.family == "single" && r.name == "Roadworn Ronin" && r.survivor == "Mercenary")
				{
					return r.tier == 1;
				}
				return false;
			case "mercenary-canopy-cutter":
				if (r.skinId == "EclipsePlaytestMercenaryE3CanopyCutter" && r.family == "single" && r.name == "Canopy Cutter" && r.survivor == "Mercenary")
				{
					return r.tier == 3;
				}
				return false;
			case "mercenary-circuit-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE2CircuitDuelist" && r.family == "single" && r.name == "Circuit Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 2;
				}
				return false;
			case "mercenary-deli-duelist":
				if (r.skinId == "EclipsePlaytestMercenaryE7DeliDuelist" && r.family == "single" && r.name == "Deli Duelist" && r.survivor == "Mercenary")
				{
					return r.tier == 7;
				}
				return false;
			case "rex-prickly-customer":
				if (r.skinId == "skinEclipseRexPricklyCustomer" && r.family == "single" && r.name == "Prickly Customer" && r.survivor == "REX")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-hole-in-one":
				if (r.skinId == "EclipseRailgunnerE1" && r.family == "railgunner" && r.name == "Hole in One" && r.survivor == "Railgunner")
				{
					return r.tier == 1;
				}
				return false;
			case "railgunner-night-sight":
				if (r.skinId == "EclipseRailgunnerE2" && r.family == "railgunner" && r.name == "Night Sight" && r.survivor == "Railgunner")
				{
					return r.tier == 2;
				}
				return false;
			case "railgunner-ring-leader":
				if (r.skinId == "EclipseRailgunnerE3" && r.family == "railgunner" && r.name == "Ring Leader" && r.survivor == "Railgunner")
				{
					return r.tier == 3;
				}
				return false;
			case "railgunner-fire-away":
				if (r.skinId == "EclipseRailgunnerE4" && r.family == "railgunner" && r.name == "Fire Away" && r.survivor == "Railgunner")
				{
					return r.tier == 4;
				}
				return false;
			case "railgunner-point-taken":
				if (r.skinId == "EclipseRailgunnerE5" && r.family == "railgunner" && r.name == "Point Taken" && r.survivor == "Railgunner")
				{
					return r.tier == 5;
				}
				return false;
			case "railgunner-express-delivery":
				if (r.skinId == "EclipseRailgunnerE6" && r.family == "railgunner" && r.name == "Express Delivery" && r.survivor == "Railgunner")
				{
					return r.tier == 6;
				}
				return false;
			case "railgunner-last-straw":
				if (r.skinId == "EclipseRailgunnerE7" && r.family == "railgunner" && r.name == "Last Straw" && r.survivor == "Railgunner")
				{
					return r.tier == 7;
				}
				return false;
			case "railgunner-horizon-lancer":
				if (r.skinId == "EclipseRailgunnerE8" && r.family == "railgunner" && r.name == "Horizon Lancer" && r.survivor == "Railgunner")
				{
					return r.tier == 8;
				}
				return false;
			case "seeker-breaditation":
				if (r.skinId == "EclipsePlaytestSeekerE7Breaditation" && r.family == "single" && r.name == "Breaditation" && r.survivor == "Seeker")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-desert-castaway":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE1" && r.family == "single" && r.name == "Desert Castaway" && r.survivor == "Void Fiend")
				{
					return r.tier == 1;
				}
				return false;
			case "void-fiend-live-wire":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE2" && r.family == "single" && r.name == "Live Wire" && r.survivor == "Void Fiend")
				{
					return r.tier == 2;
				}
				return false;
			case "void-fiend-pressure-guest":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE3" && r.family == "single" && r.name == "Pressure Guest" && r.survivor == "Void Fiend")
				{
					return r.tier == 3;
				}
				return false;
			case "void-fiend-orange-you-glad":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE4" && r.family == "single" && r.name == "Orange You Glad" && r.survivor == "Void Fiend")
				{
					return r.tier == 4;
				}
				return false;
			case "void-fiend-burnt-offering":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE5" && r.family == "single" && r.name == "Burnt Offering" && r.survivor == "Void Fiend")
				{
					return r.tier == 5;
				}
				return false;
			case "void-fiend-public-information":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE6" && r.family == "single" && r.name == "Public Information" && r.survivor == "Void Fiend")
				{
					return r.tier == 6;
				}
				return false;
			case "void-fiend-surprise-inside":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE7" && r.family == "single" && r.name == "Surprise Inside" && r.survivor == "Void Fiend")
				{
					return r.tier == 7;
				}
				return false;
			case "void-fiend-containment-impossible":
				if (r.skinId == "skinEclipsePlaytestVoidFiendE8" && r.family == "single" && r.name == "Containment Impossible" && r.survivor == "Void Fiend")
				{
					return r.tier == 8;
				}
				return false;
			case "engineer-unqualified-personnel":
				if (r.skinId == "skinRodaniusEngineerUnqualifiedPersonnel_unqualified-personnel" && r.family == "single" && r.name == "Unqualified Personnel" && r.survivor == "Engineer")
				{
					return r.tier == 2;
				}
				return false;
			case "engineer-one-man-band":
				if (r.skinId == "skinEclipsePlaytestEngineerE3_one-man-band" && r.family == "single" && r.name == "One-Man Band" && r.survivor == "Engineer")
				{
					return r.tier == 3;
				}
				return false;
			case "engineer-castle-doctrine":
				if (r.skinId == "skinEclipsePlaytestEngineerE4_castle-doctrine" && r.family == "single" && r.name == "Castle Doctrine" && r.survivor == "Engineer")
				{
					return r.tier == 4;
				}
				return false;
			case "engineer-traffic-control":
				if (r.skinId == "skinEclipsePlaytestEngineerE5_traffic-control" && r.family == "single" && r.name == "Traffic Control" && r.survivor == "Engineer")
				{
					return r.tier == 5;
				}
				return false;
			case "engineer-bubble-works":
				if (r.skinId == "skinEclipsePlaytestEngineerE6_bubble-works" && r.family == "single" && r.name == "Bubble Works" && r.survivor == "Engineer")
				{
					return r.tier == 6;
				}
				return false;
			case "engineer-primitive-solutions":
				if (r.skinId == "skinEclipsePlaytestEngineerE7_primitive-solutions" && r.family == "single" && r.name == "Primitive Solutions" && r.survivor == "Engineer")
				{
					return r.tier == 7;
				}
				return false;
			case "engineer-orbital-architect":
				if (r.skinId == "skinEclipsePlaytestEngineerE8_orbital-architect" && r.family == "single" && r.name == "Orbital Architect" && r.survivor == "Engineer")
				{
					return r.tier == 8;
				}
				return false;
			default:
				return false;
			}
		}
	}
	[Serializable]
	public sealed class AssetFile
	{
		public string path;

		public string sha256;
	}
	[Serializable]
	public sealed class SkinRecord
	{
		public int schema;

		public int tier;

		public string key;

		public string name;

		public string survivor;

		public string family;

		public string skinId;

		public string assetDirectory;

		public string icon;

		public string iconSha256;

		public AssetFile[] files;

		[NonSerialized]
		public string Root;

		public string AssetRoot => SkinDiscovery.SafePath(Root, assetDirectory);
	}
	public static class SkinDiscovery
	{
		public static string SafePath(string root, string relative)
		{
			if (string.IsNullOrEmpty(relative) || Path.IsPathRooted(relative) || relative.Split('/', '\\').Any((string x) => x == ".." || x == ""))
			{
				throw new InvalidDataException("Invalid package-relative path");
			}
			string text = Path.GetFullPath(root).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
			string fullPath = Path.GetFullPath(Path.Combine(root, relative));
			if (!fullPath.StartsWith(text, StringComparison.OrdinalIgnoreCase) && fullPath != text.TrimEnd(Path.DirectorySeparatorChar))
			{
				throw new InvalidDataException("Package path escaped root");
			}
			return fullPath;
		}

		private static IEnumerable<string> FindRecords(string root, Action<string> log)
		{
			Stack<string> todo = new Stack<string>();
			todo.Push(root);
			while (todo.Count > 0)
			{
				string dir = todo.Pop();
				string text = Path.Combine(dir, "rodanius-skin.json");
				if (File.Exists(text))
				{
					yield return text;
				}
				string[] directories;
				try
				{
					directories = Directory.GetDirectories(dir);
				}
				catch (Exception ex)
				{
					log("RODANIUS_DISCOVERY_SKIPPED " + dir + " " + ex.Message);
					continue;
				}
				string[] array = directories;
				foreach (string text2 in array)
				{
					try
					{
						if ((File.GetAttributes(text2) & FileAttributes.ReparsePoint) == 0)
						{
							todo.Push(text2);
						}
					}
					catch (Exception ex2)
					{
						log("RODANIUS_DISCOVERY_SKIPPED " + ex2.Message);
					}
				}
			}
		}

		public static string Hash(string path)
		{
			using FileStream inputStream = File.OpenRead(path);
			using SHA256 sHA = SHA256.Create();
			return BitConverter.ToString(sHA.ComputeHash(inputStream)).Replace("-", "").ToLowerInvariant();
		}

		public static List<SkinRecord> Load(string family, Action<string> log, bool verifyAssets = true)
		{
			List<SkinRecord> list = new List<SkinRecord>();
			foreach (string item in FindRecords(Paths.PluginPath, log))
			{
				try
				{
					if (new FileInfo(item).Length > 262144)
					{
						throw new InvalidDataException("Manifest too large");
					}
					SkinRecord skinRecord = JsonUtility.FromJson<SkinRecord>(File.ReadAllText(item));
					if (skinRecord == null || skinRecord.schema != 1 || !CatalogueSpecs.Matches(skinRecord))
					{
						throw new InvalidDataException("Unknown standalone skin identity");
					}
					if (family != null && skinRecord.family != family)
					{
						continue;
					}
					skinRecord.Root = Path.GetDirectoryName(item);
					SafePath(skinRecord.Root, skinRecord.assetDirectory);
					SafePath(skinRecord.Root, skinRecord.icon);
					if (verifyAssets)
					{
						if (skinRecord.files == null || skinRecord.files.Length == 0 || skinRecord.files.Length > 100)
						{
							throw new InvalidDataException("Asset inventory missing");
						}
						AssetFile[] files = skinRecord.files;
						foreach (AssetFile assetFile in files)
						{
							if (assetFile == null || assetFile.sha256 == null || assetFile.sha256.Length != 64 || Hash(SafePath(skinRecord.Root, assetFile.path)) != assetFile.sha256)
							{
								throw new InvalidDataException("Asset hash mismatch: " + ((assetFile == null) ? "null" : assetFile.path));
							}
						}
					}
					list.Add(skinRecord);
				}
				catch (Exception ex)
				{
					log("RODANIUS_SKIN_PACKAGE_REJECTED file=" + item + " error=" + ex.Message);
				}
			}
			List<SkinRecord> list2 = new List<SkinRecord>();
			foreach (IGrouping<string, SkinRecord> item2 in list.GroupBy<SkinRecord, string>((SkinRecord r) => r.skinId, StringComparer.Ordinal))
			{
				if (item2.Count() != 1)
				{
					log("RODANIUS_DUPLICATE_SKIN_PACKAGE id=" + item2.Key + " paths=" + string.Join(";", item2.Select((SkinRecord r) => r.Root)));
				}
				else
				{
					list2.Add(item2.Single());
				}
			}
			return list2.OrderBy<SkinRecord, string>((SkinRecord r) => r.survivor, StringComparer.Ordinal).ThenBy((SkinRecord r) => r.tier).ToList();
		}
	}
}