Decompiled source of Eclipse Skins v0.1.1

BepInEx/plugins/AcridBogHopper/AcridBogHopper.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestAcridE1;

[BepInPlugin("eclipseplaytest.acrid.e1", "Acrid - Bog Hopper (Playtest)", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class BogHopper : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.acrid.e1";

	public const string Version = "0.1.1";

	private static BogHopper instance;

	private string folder;

	private GameObject modelPrefab;

	private bool registered;

	private float deadline;

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

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

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

	private void CheckDeadline()
	{
		if (Time.realtimeSinceStartup > deadline)
		{
			throw new TimeoutException("Bog Hopper asset load timed out; continuing startup.");
		}
	}

	private IEnumerator Register()
	{
		GameObject val = BodyCatalog.FindBodyPrefab("CrocoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CrocoBody missing");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestAcridE1BogHopper"))
		{
			yield break;
		}
		SkinDef baseSkin = controller.skins[0];
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op));
			while (!op.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			bp = op.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Acrid base skin parameters unavailable");
		}
		SkinnedMeshRenderer[] renderers = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		List<RendererInfo> infos = new List<RendererInfo>();
		List<MeshReplacement> replacements = new List<MeshReplacement>();
		string[] array = new string[1] { "body" };
		foreach (string part in array)
		{
			string expected = "CrocoMesh";
			SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == expected);
			if (target.bones.Length != 94)
			{
				throw new InvalidOperationException(expected + " unexpected bone count");
			}
			Mesh reference = target.sharedMesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
				reference = val2.mesh;
				if (!Object.op_Implicit((Object)(object)reference))
				{
					AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
					retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2));
					while (!op2.IsDone)
					{
						CheckDeadline();
						yield return null;
					}
					reference = op2.Result;
				}
			}
			if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != 94)
			{
				throw new InvalidOperationException(expected + " invalid bind pose");
			}
			RendererInfo info = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material val3 = info.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)val3) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3));
				while (!op3.IsDone)
				{
					CheckDeadline();
					yield return null;
				}
				val3 = op3.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(expected + " no native material");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, part + ".meshbin"), target, reference);
			((Object)val4).name = "EclipseAcridE1_" + part;
			Material val5 = new Material(val3)
			{
				name = "matEclipseAcridE1_" + part
			};
			val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
			val5.SetColor("_Color", Color.white);
			val5.SetFloat("_NormalStrength", 0f);
			val5.SetFloat("_Smoothness", 0.12f);
			val5.SetFloat("_SpecularStrength", 0.15f);
			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("FORCE_SPEC");
			val5.SetFloat("_ForceSpecOn", 0f);
			val5.DisableKeyword("LIMBREMOVAL");
			val5.SetFloat("_LimbRemovalOn", 0f);
			info.defaultMaterial = val5;
			info.defaultMaterialAddress = new AssetReferenceT<Material>("");
			infos.Add(info);
			replacements.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ACRID_E1_PART_READY " + part + " vertices=" + val4.vertexCount + " bones=" + target.bones.Length));
			yield return null;
		}
		SkinnedMeshRenderer renderer = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "CrocoSpineMesh");
		Mesh val6 = new Mesh
		{
			name = "EclipseAcridE1EmptySpines"
		};
		val6.vertices = Array.Empty<Vector3>();
		val6.triangles = Array.Empty<int>();
		replacements.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)renderer,
			mesh = val6,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		SkinDefParams val7 = ScriptableObject.CreateInstance<SkinDefParams>();
		val7.rendererInfos = infos.ToArray();
		val7.meshReplacements = replacements.ToArray();
		SkinDef val8 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val8).name = "EclipsePlaytestAcridE1BogHopper";
		val8.nameToken = "ECLIPSE_PLAYTEST_ACRID_E1_BOG_HOPPER";
		LanguageAPI.Add(val8.nameToken, "Bog Hopper (Playtest)");
		val8.unlockableDef = null;
		val8.rootObject = modelPrefab;
		val8.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val8.skinDefParams = val7;
		Texture2D val9 = ReadTexture("skin-icon.png", linear: false);
		val8.icon = Sprite.Create(val9, new Rect(0f, 0f, (float)((Texture)val9).width, (float)((Texture)val9).height), new Vector2(0.5f, 0.5f));
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val8 }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ACRID_E1_REGISTERED version=0.1.1 model=M018 unlocked=true");
	}

	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 == "CrocoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				(((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>()).skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			}
		}
	}

	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_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: 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_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: 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_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_0360: Unknown result type (might be due to invalid IL or missing references)
		//IL_0372: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: 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_038a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0392: 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_03a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b4: Expected O, but got Unknown
		//IL_024f: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: 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("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 != 94)
		{
			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 text = Encoding.UTF8.GetString(binaryReader.ReadBytes(num4));
			if (renderer.bones.Length != num3 || !Object.op_Implicit((Object)(object)renderer.bones[i]) || ((Object)renderer.bones[i]).name != text)
			{
				throw new InvalidDataException("Native bone slot mismatch: " + i + " expected " + text);
			}
			array[i] = i;
		}
		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 j = 0; j < num; j++)
		{
			array2[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array3[j] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array4[j] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			int[] array6 = new int[4];
			for (int k = 0; k < 4; k++)
			{
				int num5 = binaryReader.ReadInt32();
				if (num5 < 0 || num5 >= num3)
				{
					throw new InvalidDataException("Bone out of range.");
				}
				array6[k] = array[num5];
			}
			float[] array7 = new float[4];
			for (int l = 0; l < 4; l++)
			{
				array7[l] = 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[j]) || !Finite(array3[j]))
			{
				throw new InvalidDataException("Non-finite vertex.");
			}
			int num6 = j;
			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[num6] = val;
		}
		int[] array8 = new int[num2];
		for (int num7 = 0; num7 < num2; num7++)
		{
			array8[num7] = binaryReader.ReadInt32();
			if (array8[num7] < 0 || array8[num7] >= 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 = "AcridBogHopperMesh",
			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;
	}
}

BepInEx/plugins/EclipsePlaytestBanditE1/BanditE1Playtest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipseBanditPlaytest;

[BepInPlugin("eclipseplaytest.bandit.e1", "Bandit Corner Crew Playtest", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class BanditE1Playtest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.bandit.e1";

	public const string Version = "0.1.1";

	private static BanditE1Playtest instance;

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

	private float registrationDeadline;

	private string folder;

	private SkinDef skin;

	private Material material;

	private GameObject modelPrefab;

	private bool registered;

	private void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		LanguageAPI.Add("ECLIPSEPLAYTEST_BANDIT_E1_NAME", "Bandit - Corner Crew (Playtest)");
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(BanditE1Playtest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("BANDIT_E1_PLAYTEST_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"BANDIT_E1_PLAYTEST_REGISTRATION_BEGIN version=0.1.1 revision=M005");
		GameObject val = BodyCatalog.FindBodyPrefab("Bandit2Body");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("Bandit2Body missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0)
		{
			throw new InvalidOperationException("Bandit base skin missing.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestBanditE1"))
		{
			yield break;
		}
		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("base parameters");
				yield return null;
			}
			baseParams = load.Result;
		}
		if (!Object.op_Implicit((Object)(object)baseParams))
		{
			throw new InvalidOperationException("Bandit base parameters unavailable.");
		}
		Renderer[] renderers = modelPrefab.GetComponentsInChildren<Renderer>(true);
		SkinnedMeshRenderer target = renderers.OfType<SkinnedMeshRenderer>().Single((SkinnedMeshRenderer r) => ((Object)r).name == "Bandit2BodyMesh");
		if (target.bones.Length != 98)
		{
			throw new InvalidOperationException("Unexpected Bandit skeleton: " + target.bones.Length);
		}
		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) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Mesh> load2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(load2));
				while (!load2.IsDone)
				{
					CheckLoadDeadline("native bind mesh");
					yield return null;
				}
				referenceMesh = load2.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)referenceMesh) || referenceMesh.bindposes.Length != target.bones.Length)
		{
			throw new InvalidOperationException("Native bindposes unavailable or mismatched.");
		}
		RendererInfo val3 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material val4 = val3.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)val4) && val3.defaultMaterialAddress != null && ((AssetReference)val3.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> load3 = Addressables.LoadAssetAsync<Material>(((AssetReference)val3.defaultMaterialAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(load3));
			while (!load3.IsDone)
			{
				CheckLoadDeadline("native material");
				yield return null;
			}
			val4 = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)val4))
		{
			val4 = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.shader))
		{
			throw new InvalidOperationException("Native Bandit shader unavailable.");
		}
		material = new Material(val4)
		{
			name = "matEclipsePlaytestBanditE1"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0f);
		material.SetFloat("_Smoothness", 0.18f);
		material.SetFloat("_SpecularStrength", 0.25f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<MeshReplacement> list = new List<MeshReplacement>();
		List<RendererInfo> list2 = new List<RendererInfo>();
		string[][] array = new string[3][]
		{
			new string[2] { "Bandit2BodyMesh", "body" },
			new string[2] { "BanditShotgunMesh", "shotgun" },
			new string[2] { "BanditPistolMesh", "pistol" }
		};
		foreach (string[] pair in array)
		{
			Renderer renderer = renderers.Single((Renderer r) => ((Object)r).name == pair[0]);
			if (pair[1] != "body" && !Object.op_Implicit((Object)(object)((Component)renderer).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Weapon MeshFilter missing: " + pair[0]);
			}
			Mesh val5 = ReadMesh(Path.Combine(folder, pair[1] + ".meshbin"), target, referenceMesh);
			((Object)val5).name = "meshEclipsePlaytestBanditE1_" + pair[1];
			list.Add(new MeshReplacement
			{
				renderer = renderer,
				mesh = val5,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			RendererInfo item = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)renderer);
			item.defaultMaterial = material;
			item.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list2.Add(item);
		}
		GameObjectActivation[] gameObjectActivations = ((IEnumerable<string>)new string[4] { "Bandit2ArmsMesh", "Bandit2CoatMesh", "Bandit2HatMesh", "Bandit2AccessoriesMesh" }).Select((Func<string, GameObjectActivation>)((string n) => new GameObjectActivation
		{
			gameObject = ((Component)renderers.Single((Renderer r) => ((Object)r).name == n)).gameObject,
			shouldActivate = false
		})).ToArray();
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val6).name = "paramsEclipsePlaytestBanditE1";
		val6.rendererInfos = list2.ToArray();
		val6.meshReplacements = list.ToArray();
		val6.gameObjectActivations = gameObjectActivations;
		val6.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
		val6.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
		val6.lightReplacements = Array.Empty<LightInfo>();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestBanditE1";
		skin.nameToken = "ECLIPSEPLAYTEST_BANDIT_E1_NAME";
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)180, (byte)183, (byte)171, byte.MaxValue),
			new Color32((byte)23, (byte)29, (byte)34, byte.MaxValue),
			new Color32((byte)23, (byte)41, (byte)69, byte.MaxValue),
			new Color32((byte)114, (byte)35, (byte)45, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.unlockableName = "";
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val6;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E1_PLAYTEST_REGISTERED version=0.1.1 revision=M005 unlocked=true skin=" + ((Object)skin).name));
	}

	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 == "Bandit2Body"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E1_PLAYTEST_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 98)
		{
			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 = "meshEclipsePlaytestBanditE1",
			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;
	}
}

BepInEx/plugins/EclipsePlaytestBanditE2/BanditE2Playtest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipseBanditPlaytest;

[BepInPlugin("eclipseplaytest.bandit.e2", "Bandit After Hours Playtest", "0.1.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class BanditE2Playtest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.bandit.e2";

	public const string Version = "0.1.3";

	private static BanditE2Playtest instance;

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

	private float registrationDeadline;

	private string folder;

	private SkinDef skin;

	private Material material;

	private GameObject modelPrefab;

	private bool registered;

	private void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		LanguageAPI.Add("ECLIPSEPLAYTEST_BANDIT_E2_NAME", "Bandit - After Hours (Playtest)");
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(BanditE2Playtest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("BANDIT_E2_PLAYTEST_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"BANDIT_E2_PLAYTEST_REGISTRATION_BEGIN version=0.1.3 revision=M005");
		GameObject val = BodyCatalog.FindBodyPrefab("Bandit2Body");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("Bandit2Body missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0)
		{
			throw new InvalidOperationException("Bandit base skin missing.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestBanditE2"))
		{
			yield break;
		}
		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("base parameters");
				yield return null;
			}
			baseParams = load.Result;
		}
		if (!Object.op_Implicit((Object)(object)baseParams))
		{
			throw new InvalidOperationException("Bandit base parameters unavailable.");
		}
		Renderer[] renderers = modelPrefab.GetComponentsInChildren<Renderer>(true);
		SkinnedMeshRenderer target = renderers.OfType<SkinnedMeshRenderer>().Single((SkinnedMeshRenderer r) => ((Object)r).name == "Bandit2BodyMesh");
		if (target.bones.Length != 98)
		{
			throw new InvalidOperationException("Unexpected Bandit skeleton: " + target.bones.Length);
		}
		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) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Mesh> load2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(load2));
				while (!load2.IsDone)
				{
					CheckLoadDeadline("native bind mesh");
					yield return null;
				}
				referenceMesh = load2.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)referenceMesh) || referenceMesh.bindposes.Length != target.bones.Length)
		{
			throw new InvalidOperationException("Native bindposes unavailable or mismatched.");
		}
		RendererInfo val3 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material val4 = val3.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)val4) && val3.defaultMaterialAddress != null && ((AssetReference)val3.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> load3 = Addressables.LoadAssetAsync<Material>(((AssetReference)val3.defaultMaterialAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(load3));
			while (!load3.IsDone)
			{
				CheckLoadDeadline("native material");
				yield return null;
			}
			val4 = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)val4))
		{
			val4 = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.shader))
		{
			throw new InvalidOperationException("Native Bandit shader unavailable.");
		}
		material = new Material(val4)
		{
			name = "matEclipsePlaytestBanditE2"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0f);
		material.SetFloat("_Smoothness", 0.18f);
		material.SetFloat("_SpecularStrength", 0.25f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<MeshReplacement> list = new List<MeshReplacement>();
		List<RendererInfo> list2 = new List<RendererInfo>();
		string[][] array = new string[3][]
		{
			new string[2] { "Bandit2BodyMesh", "body" },
			new string[2] { "BanditShotgunMesh", "shotgun" },
			new string[2] { "BanditPistolMesh", "pistol" }
		};
		foreach (string[] pair in array)
		{
			Renderer renderer = renderers.Single((Renderer r) => ((Object)r).name == pair[0]);
			if (pair[1] != "body" && !Object.op_Implicit((Object)(object)((Component)renderer).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Weapon MeshFilter missing: " + pair[0]);
			}
			Mesh val5 = ReadMesh(Path.Combine(folder, pair[1] + ".meshbin"), target, referenceMesh);
			((Object)val5).name = "meshEclipsePlaytestBanditE2_" + pair[1];
			list.Add(new MeshReplacement
			{
				renderer = renderer,
				mesh = val5,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			RendererInfo item = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)renderer);
			item.defaultMaterial = material;
			item.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list2.Add(item);
		}
		GameObjectActivation[] gameObjectActivations = ((IEnumerable<string>)new string[4] { "Bandit2ArmsMesh", "Bandit2CoatMesh", "Bandit2HatMesh", "Bandit2AccessoriesMesh" }).Select((Func<string, GameObjectActivation>)((string n) => new GameObjectActivation
		{
			gameObject = ((Component)renderers.Single((Renderer r) => ((Object)r).name == n)).gameObject,
			shouldActivate = false
		})).ToArray();
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val6).name = "paramsEclipsePlaytestBanditE2";
		val6.rendererInfos = list2.ToArray();
		val6.meshReplacements = list.ToArray();
		val6.gameObjectActivations = gameObjectActivations;
		val6.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
		val6.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
		val6.lightReplacements = Array.Empty<LightInfo>();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestBanditE2";
		skin.nameToken = "ECLIPSEPLAYTEST_BANDIT_E2_NAME";
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)62, (byte)68, (byte)71, byte.MaxValue),
			new Color32((byte)24, (byte)28, (byte)31, byte.MaxValue),
			new Color32((byte)96, (byte)95, (byte)79, byte.MaxValue),
			new Color32((byte)112, (byte)34, (byte)31, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.unlockableName = "";
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val6;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E2_PLAYTEST_REGISTERED version=0.1.3 revision=M005 unlocked=true skin=" + ((Object)skin).name));
	}

	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 == "Bandit2Body"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E2_PLAYTEST_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 98)
		{
			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 = "meshEclipsePlaytestBanditE2",
			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;
	}
}

BepInEx/plugins/EclipsePlaytestBanditE3/BanditE3Playtest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipseBanditPlaytest;

[BepInPlugin("eclipseplaytest.bandit.e3", "Bandit House Always Wins Playtest", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class BanditE3Playtest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.bandit.e3";

	public const string Version = "0.1.0";

	private static BanditE3Playtest instance;

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

	private float registrationDeadline;

	private string folder;

	private SkinDef skin;

	private Material material;

	private GameObject modelPrefab;

	private bool registered;

	private void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		LanguageAPI.Add("ECLIPSEPLAYTEST_BANDIT_E3_NAME", "Bandit - House Always Wins (Playtest)");
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(BanditE3Playtest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("BANDIT_E3_PLAYTEST_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"BANDIT_E3_PLAYTEST_REGISTRATION_BEGIN version=0.1.0 revision=M001");
		GameObject val = BodyCatalog.FindBodyPrefab("Bandit2Body");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("Bandit2Body missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null || controller.skins.Length == 0)
		{
			throw new InvalidOperationException("Bandit base skin missing.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestBanditE3"))
		{
			yield break;
		}
		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("base parameters");
				yield return null;
			}
			baseParams = load.Result;
		}
		if (!Object.op_Implicit((Object)(object)baseParams))
		{
			throw new InvalidOperationException("Bandit base parameters unavailable.");
		}
		Renderer[] renderers = modelPrefab.GetComponentsInChildren<Renderer>(true);
		SkinnedMeshRenderer target = renderers.OfType<SkinnedMeshRenderer>().Single((SkinnedMeshRenderer r) => ((Object)r).name == "Bandit2BodyMesh");
		if (target.bones.Length != 98)
		{
			throw new InvalidOperationException("Unexpected Bandit skeleton: " + target.bones.Length);
		}
		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) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Mesh> load2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(load2));
				while (!load2.IsDone)
				{
					CheckLoadDeadline("native bind mesh");
					yield return null;
				}
				referenceMesh = load2.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)referenceMesh) || referenceMesh.bindposes.Length != target.bones.Length)
		{
			throw new InvalidOperationException("Native bindposes unavailable or mismatched.");
		}
		RendererInfo val3 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material val4 = val3.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)val4) && val3.defaultMaterialAddress != null && ((AssetReference)val3.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> load3 = Addressables.LoadAssetAsync<Material>(((AssetReference)val3.defaultMaterialAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(load3));
			while (!load3.IsDone)
			{
				CheckLoadDeadline("native material");
				yield return null;
			}
			val4 = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)val4))
		{
			val4 = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)val4) || !Object.op_Implicit((Object)(object)val4.shader))
		{
			throw new InvalidOperationException("Native Bandit shader unavailable.");
		}
		material = new Material(val4)
		{
			name = "matEclipsePlaytestBanditE3"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0f);
		material.SetFloat("_Smoothness", 0.18f);
		material.SetFloat("_SpecularStrength", 0.25f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<MeshReplacement> list = new List<MeshReplacement>();
		List<RendererInfo> list2 = new List<RendererInfo>();
		string[][] array = new string[3][]
		{
			new string[2] { "Bandit2BodyMesh", "body" },
			new string[2] { "BanditShotgunMesh", "shotgun" },
			new string[2] { "BanditPistolMesh", "pistol" }
		};
		foreach (string[] pair in array)
		{
			Renderer renderer = renderers.Single((Renderer r) => ((Object)r).name == pair[0]);
			if (pair[1] != "body" && !Object.op_Implicit((Object)(object)((Component)renderer).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Weapon MeshFilter missing: " + pair[0]);
			}
			Mesh val5 = ReadMesh(Path.Combine(folder, pair[1] + ".meshbin"), target, referenceMesh);
			((Object)val5).name = "meshEclipsePlaytestBanditE3_" + pair[1];
			list.Add(new MeshReplacement
			{
				renderer = renderer,
				mesh = val5,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			RendererInfo item = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)renderer);
			item.defaultMaterial = material;
			item.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list2.Add(item);
		}
		GameObjectActivation[] gameObjectActivations = ((IEnumerable<string>)new string[4] { "Bandit2ArmsMesh", "Bandit2CoatMesh", "Bandit2HatMesh", "Bandit2AccessoriesMesh" }).Select((Func<string, GameObjectActivation>)((string n) => new GameObjectActivation
		{
			gameObject = ((Component)renderers.Single((Renderer r) => ((Object)r).name == n)).gameObject,
			shouldActivate = false
		})).ToArray();
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val6).name = "paramsEclipsePlaytestBanditE3";
		val6.rendererInfos = list2.ToArray();
		val6.meshReplacements = list.ToArray();
		val6.gameObjectActivations = gameObjectActivations;
		val6.projectileGhostReplacements = Array.Empty<ProjectileGhostReplacement>();
		val6.minionSkinReplacements = Array.Empty<MinionSkinReplacement>();
		val6.lightReplacements = Array.Empty<LightInfo>();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestBanditE3";
		skin.nameToken = "ECLIPSEPLAYTEST_BANDIT_E3_NAME";
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)205, (byte)202, (byte)186, byte.MaxValue),
			new Color32((byte)20, (byte)23, (byte)30, byte.MaxValue),
			new Color32((byte)120, (byte)39, (byte)53, byte.MaxValue),
			new Color32((byte)188, (byte)143, (byte)59, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.unlockableName = "";
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val6;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E3_PLAYTEST_REGISTERED version=0.1.0 revision=M001 unlocked=true skin=" + ((Object)skin).name));
	}

	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 == "Bandit2Body"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("BANDIT_E3_PLAYTEST_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 98)
		{
			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 = "meshEclipsePlaytestBanditE3",
			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;
	}
}

BepInEx/plugins/EclipsePlaytestMULTDeepSalvageUnit/MULTDeepSalvageUnit.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using EntityStates;
using EntityStates.Toolbot;
using HG.Reflection;
using HarmonyLib;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMULTDeepSalvage;

[BepInPlugin("eclipseplaytest.mul-t.e3", "MUL-T - Deep-Salvage Unit (Playtest)", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MULTDeepSalvageUnit : 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;
		}
	}

	[HarmonyPatch(typeof(ToolbotDualWield), "OnEnter")]
	private static class PowerModePatch
	{
		private static readonly FieldInfo Left = AccessTools.Field(typeof(ToolbotDualWield), "coverLeftInstance");

		private static readonly FieldInfo Right = AccessTools.Field(typeof(ToolbotDualWield), "coverRightInstance");

		private static readonly FieldInfo Prefab = AccessTools.Field(typeof(ToolbotDualWield), "coverPrefab");

		private static void Postfix(ToolbotDualWield __instance)
		{
			if (!Object.op_Implicit((Object)(object)instance) || !instance.registered)
			{
				return;
			}
			try
			{
				CharacterBody component = ((Component)((EntityState)__instance).outer).gameObject.GetComponent<CharacterBody>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.modelLocator) || !Object.op_Implicit((Object)(object)component.modelLocator.modelTransform))
				{
					return;
				}
				SkinnedMeshRenderer val = ((IEnumerable<SkinnedMeshRenderer>)((Component)component.modelLocator.modelTransform).GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 64 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head")));
				object? value = Prefab.GetValue(null);
				GameObject val2 = (GameObject)((value is GameObject) ? value : null);
				SkinnedMeshRenderer val3 = (Object.op_Implicit((Object)(object)val2) ? ((IEnumerable<SkinnedMeshRenderer>)val2.GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 2)) : null);
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.sharedMesh))
				{
					throw new InvalidOperationException("Power Mode native renderer unavailable.");
				}
				FieldInfo[] array = new FieldInfo[2] { Left, Right };
				for (int num = 0; num < array.Length; num++)
				{
					object? value2 = array[num].GetValue(__instance);
					GameObject val4 = (GameObject)((value2 is GameObject) ? value2 : null);
					if (Object.op_Implicit((Object)(object)val4))
					{
						SkinnedMeshRenderer val5 = ((IEnumerable<SkinnedMeshRenderer>)val4.GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 2));
						if (!Object.op_Implicit((Object)(object)val5))
						{
							throw new InvalidOperationException("Power Mode cover renderer missing.");
						}
						if (!Object.op_Implicit((Object)(object)instance.powerMesh))
						{
							instance.powerMesh = instance.ReadMesh(Path.Combine(instance.folder, "power.meshbin"), val5, val3.sharedMesh);
						}
						val4.AddComponent<PowerCoverAppearance>().Initialize(instance, val, val5, val3);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)("ECLIPSEPLAYTEST_MULT_E3_POWER_APPLY_FAILED: " + ex));
			}
		}
	}

	public sealed class PowerCoverAppearance : MonoBehaviour
	{
		private MULTDeepSalvageUnit owner;

		private SkinnedMeshRenderer main;

		private SkinnedMeshRenderer target;

		private Mesh nativeMesh;

		private Material[] nativeMaterials;

		private Bounds nativeBounds;

		private Mesh lastMainMesh;

		private bool initialized;

		public void Initialize(MULTDeepSalvageUnit plugin, SkinnedMeshRenderer body, SkinnedMeshRenderer cover, SkinnedMeshRenderer reference)
		{
			//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)
			owner = plugin;
			main = body;
			target = cover;
			nativeMesh = reference.sharedMesh;
			nativeMaterials = (Material[])((Renderer)reference).sharedMaterials.Clone();
			nativeBounds = ((Renderer)reference).localBounds;
			initialized = true;
			ApplyForCurrentSkin();
		}

		private void LateUpdate()
		{
			if (initialized && Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)main) && Object.op_Implicit((Object)(object)target) && (Object)(object)lastMainMesh != (Object)(object)main.sharedMesh)
			{
				ApplyForCurrentSkin();
			}
		}

		private void ApplyForCurrentSkin()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			lastMainMesh = main.sharedMesh;
			if ((Object)(object)lastMainMesh == (Object)(object)owner.mesh)
			{
				target.sharedMesh = owner.powerMesh;
				((Renderer)target).sharedMaterials = (Material[])(object)new Material[1] { owner.material };
				((Renderer)target).localBounds = owner.powerMesh.bounds;
			}
			else
			{
				RestoreIfOwned();
			}
		}

		public void RestoreIfOwned()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)owner) && (Object)(object)target.sharedMesh == (Object)(object)owner.powerMesh)
			{
				target.sharedMesh = nativeMesh;
				((Renderer)target).sharedMaterials = nativeMaterials;
				((Renderer)target).localBounds = nativeBounds;
			}
		}

		private void OnDestroy()
		{
			RestoreIfOwned();
		}
	}

	public const string Guid = "eclipseplaytest.mul-t.e3";

	public const string Version = "0.1.0";

	private static MULTDeepSalvageUnit 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 Mesh powerMesh;

	private Harmony powerHooks;

	private bool registered;

	private static readonly Design[] Designs = new Design[1]
	{
		new Design("deep-salvage-unit", "MUL-T - Deep-Salvage Unit (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)89, (byte)133, (byte)124, byte.MaxValue),
			new Color32((byte)24, (byte)37, (byte)42, byte.MaxValue),
			new Color32((byte)192, (byte)153, (byte)72, byte.MaxValue),
			new Color32((byte)174, (byte)190, (byte)181, byte.MaxValue)
		})
	};

	private void Awake()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(MULTDeepSalvageUnit));
		powerHooks = new Harmony("eclipseplaytest.mul-t.e3");
		powerHooks.PatchAll(typeof(PowerModePatch));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_MULT_E3_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_MULT_E3_REGISTRATION_BEGIN async loader 0.1.0");
		GameObject val = BodyCatalog.FindBodyPrefab("ToolbotBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("ToolbotBody is missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytest_MULT_E3"))
		{
			yield break;
		}
		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("MUL-T's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 64 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 MUL-T bind pose does not match the renderer.");
		}
		RendererInfo originalInfo = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("MUL-T's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = folder;
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "MULTDeepSalvageUnit_" + design.Slug;
			material = new Material(source)
			{
				name = "matMULTDeepSalvageUnit_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)Texture2D.normalTexture);
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0.35f);
			material.SetColor("_EmColor", Color.white);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			val4.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
			{
				new MeshReplacement
				{
					renderer = (Renderer)(object)target,
					mesh = mesh,
					meshAddress = new AssetReferenceT<Mesh>("")
				}
			};
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinEclipsePlaytest_MULT_E3";
			skin.nameToken = "ECLIPSEPLAYTEST_MULT_E3_DEEP_SALVAGE_UNIT_NAME";
			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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E3_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E3_REGISTERED count=" + additions.Count + " version=0.1.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 == "ToolbotBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E3_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: 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_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: 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_0347: 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_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: 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_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: 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_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Expected O, but got Unknown
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: 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)) != "MTE1")
		{
			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 != renderer.bones.Length)
		{
			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 = "MULTDeepSalvageUnit",
			indexFormat = (IndexFormat)(num > 65535),
			vertices = array2,
			normals = array3,
			uv = array4,
			boneWeights = array5,
			bindposes = reference.bindposes,
			triangles = array8
		};
		val2.RecalculateBounds();
		val2.RecalculateTangents();
		return val2;
	}

	private void OnDestroy()
	{
		if (powerHooks != null)
		{
			powerHooks.UnpatchSelf();
		}
		PowerCoverAppearance[] array = Object.FindObjectsOfType<PowerCoverAppearance>();
		foreach (PowerCoverAppearance obj in array)
		{
			obj.RestoreIfOwned();
			Object.Destroy((Object)(object)obj);
		}
		RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins;
	}

	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;
	}
}

BepInEx/plugins/EclipsePlaytestMULTTimberHauler/MULTTimberHauler.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using EntityStates;
using EntityStates.Toolbot;
using HG.Reflection;
using HarmonyLib;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMULTTimber;

[BepInPlugin("eclipseplaytest.mul-t.e2", "MUL-T - Timber Hauler (Playtest)", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MULTTimberHauler : 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;
		}
	}

	[HarmonyPatch(typeof(ToolbotDualWield), "OnEnter")]
	private static class PowerModePatch
	{
		private static readonly FieldInfo Left = AccessTools.Field(typeof(ToolbotDualWield), "coverLeftInstance");

		private static readonly FieldInfo Right = AccessTools.Field(typeof(ToolbotDualWield), "coverRightInstance");

		private static readonly FieldInfo Prefab = AccessTools.Field(typeof(ToolbotDualWield), "coverPrefab");

		private static void Postfix(ToolbotDualWield __instance)
		{
			if (!Object.op_Implicit((Object)(object)instance) || !instance.registered)
			{
				return;
			}
			try
			{
				CharacterBody component = ((Component)((EntityState)__instance).outer).gameObject.GetComponent<CharacterBody>();
				if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.modelLocator) || !Object.op_Implicit((Object)(object)component.modelLocator.modelTransform))
				{
					return;
				}
				SkinnedMeshRenderer val = ((IEnumerable<SkinnedMeshRenderer>)((Component)component.modelLocator.modelTransform).GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 64 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head")));
				object? value = Prefab.GetValue(null);
				GameObject val2 = (GameObject)((value is GameObject) ? value : null);
				SkinnedMeshRenderer val3 = (Object.op_Implicit((Object)(object)val2) ? ((IEnumerable<SkinnedMeshRenderer>)val2.GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 2)) : null);
				if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val3) || !Object.op_Implicit((Object)(object)val3.sharedMesh))
				{
					throw new InvalidOperationException("Power Mode native renderer unavailable.");
				}
				FieldInfo[] array = new FieldInfo[2] { Left, Right };
				for (int num = 0; num < array.Length; num++)
				{
					object? value2 = array[num].GetValue(__instance);
					GameObject val4 = (GameObject)((value2 is GameObject) ? value2 : null);
					if (Object.op_Implicit((Object)(object)val4))
					{
						SkinnedMeshRenderer val5 = ((IEnumerable<SkinnedMeshRenderer>)val4.GetComponentsInChildren<SkinnedMeshRenderer>(true)).FirstOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => r.bones.Length == 2));
						if (!Object.op_Implicit((Object)(object)val5))
						{
							throw new InvalidOperationException("Power Mode cover renderer missing.");
						}
						if (!Object.op_Implicit((Object)(object)instance.powerMesh))
						{
							instance.powerMesh = instance.ReadMesh(Path.Combine(instance.folder, "power.meshbin"), val5, val3.sharedMesh);
						}
						val4.AddComponent<PowerCoverAppearance>().Initialize(instance, val, val5, val3);
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)instance).Logger.LogError((object)("ECLIPSEPLAYTEST_MULT_E2_POWER_APPLY_FAILED: " + ex));
			}
		}
	}

	public sealed class PowerCoverAppearance : MonoBehaviour
	{
		private MULTTimberHauler owner;

		private SkinnedMeshRenderer main;

		private SkinnedMeshRenderer target;

		private Mesh nativeMesh;

		private Material[] nativeMaterials;

		private Bounds nativeBounds;

		private Mesh lastMainMesh;

		private bool initialized;

		public void Initialize(MULTTimberHauler plugin, SkinnedMeshRenderer body, SkinnedMeshRenderer cover, SkinnedMeshRenderer reference)
		{
			//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)
			owner = plugin;
			main = body;
			target = cover;
			nativeMesh = reference.sharedMesh;
			nativeMaterials = (Material[])((Renderer)reference).sharedMaterials.Clone();
			nativeBounds = ((Renderer)reference).localBounds;
			initialized = true;
			ApplyForCurrentSkin();
		}

		private void LateUpdate()
		{
			if (initialized && Object.op_Implicit((Object)(object)owner) && Object.op_Implicit((Object)(object)main) && Object.op_Implicit((Object)(object)target) && (Object)(object)lastMainMesh != (Object)(object)main.sharedMesh)
			{
				ApplyForCurrentSkin();
			}
		}

		private void ApplyForCurrentSkin()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			lastMainMesh = main.sharedMesh;
			if ((Object)(object)lastMainMesh == (Object)(object)owner.mesh)
			{
				target.sharedMesh = owner.powerMesh;
				((Renderer)target).sharedMaterials = (Material[])(object)new Material[1] { owner.material };
				((Renderer)target).localBounds = owner.powerMesh.bounds;
			}
			else
			{
				RestoreIfOwned();
			}
		}

		public void RestoreIfOwned()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)target) && Object.op_Implicit((Object)(object)owner) && (Object)(object)target.sharedMesh == (Object)(object)owner.powerMesh)
			{
				target.sharedMesh = nativeMesh;
				((Renderer)target).sharedMaterials = nativeMaterials;
				((Renderer)target).localBounds = nativeBounds;
			}
		}

		private void OnDestroy()
		{
			RestoreIfOwned();
		}
	}

	public const string Guid = "eclipseplaytest.mul-t.e2";

	public const string Version = "0.1.0";

	private static MULTTimberHauler 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 Mesh powerMesh;

	private Harmony powerHooks;

	private bool registered;

	private static readonly Design[] Designs = new Design[1]
	{
		new Design("timber-hauler", "MUL-T - Timber Hauler (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)80, (byte)99, (byte)47, byte.MaxValue),
			new Color32((byte)28, (byte)36, (byte)27, byte.MaxValue),
			new Color32((byte)204, (byte)88, (byte)29, byte.MaxValue),
			new Color32((byte)210, (byte)151, (byte)55, byte.MaxValue)
		})
	};

	private void Awake()
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(MULTTimberHauler));
		powerHooks = new Harmony("eclipseplaytest.mul-t.e2");
		powerHooks.PatchAll(typeof(PowerModePatch));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_MULT_E2_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_MULT_E2_REGISTRATION_BEGIN async loader 0.1.0");
		GameObject val = BodyCatalog.FindBodyPrefab("ToolbotBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("ToolbotBody is missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytest_MULT_E2"))
		{
			yield break;
		}
		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("MUL-T's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 64 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 MUL-T bind pose does not match the renderer.");
		}
		RendererInfo originalInfo = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("MUL-T's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = folder;
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "MULTTimberHauler_" + design.Slug;
			material = new Material(source)
			{
				name = "matMULTTimberHauler_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)Texture2D.normalTexture);
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0.35f);
			material.SetColor("_EmColor", Color.white);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			val4.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
			{
				new MeshReplacement
				{
					renderer = (Renderer)(object)target,
					mesh = mesh,
					meshAddress = new AssetReferenceT<Mesh>("")
				}
			};
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinEclipsePlaytest_MULT_E2";
			skin.nameToken = "ECLIPSEPLAYTEST_MULT_E2_TIMBER_HAULER_NAME";
			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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E2_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E2_REGISTERED count=" + additions.Count + " version=0.1.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 == "ToolbotBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E2_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: 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_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: 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_0347: 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_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: 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_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0389: Unknown result type (might be due to invalid IL or missing references)
		//IL_0395: 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_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ab: Expected O, but got Unknown
		//IL_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_0256: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d3: 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)) != "MTE1")
		{
			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 != renderer.bones.Length)
		{
			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 = "MULTTimberHauler",
			indexFormat = (IndexFormat)(num > 65535),
			vertices = array2,
			normals = array3,
			uv = array4,
			boneWeights = array5,
			bindposes = reference.bindposes,
			triangles = array8
		};
		val2.RecalculateBounds();
		val2.RecalculateTangents();
		return val2;
	}

	private void OnDestroy()
	{
		if (powerHooks != null)
		{
			powerHooks.UnpatchSelf();
		}
		PowerCoverAppearance[] array = Object.FindObjectsOfType<PowerCoverAppearance>();
		foreach (PowerCoverAppearance obj in array)
		{
			obj.RestoreIfOwned();
			Object.Destroy((Object)(object)obj);
		}
		RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised -= SyncDisplaySkins;
	}

	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;
	}
}

BepInEx/plugins/EclipsePlaytestMULTYardSalvager/MULTYardSalvager.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMULT;

[BepInPlugin("eclipseplaytest.mul-t.e1", "MUL-T - Yard Salvager (Playtest)", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MULTYardSalvager : 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 = "eclipseplaytest.mul-t.e1";

	public const string Version = "0.1.0";

	private static MULTYardSalvager 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[1]
	{
		new Design("yard-salvager", "MUL-T - Yard Salvager (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)189, (byte)126, (byte)35, byte.MaxValue),
			new Color32((byte)33, (byte)40, (byte)40, byte.MaxValue),
			new Color32((byte)125, (byte)42, (byte)25, byte.MaxValue),
			new Color32((byte)228, (byte)209, (byte)155, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_MULT_E1_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_MULT_E1_REGISTRATION_BEGIN async loader 0.1.0");
		GameObject val = BodyCatalog.FindBodyPrefab("ToolbotBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("ToolbotBody is missing.");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytest_MULT_E1"))
		{
			yield break;
		}
		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("MUL-T's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 64 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 MUL-T bind pose does not match the renderer.");
		}
		RendererInfo originalInfo = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("MUL-T's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = folder;
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "MULTYardSalvager_" + design.Slug;
			material = new Material(source)
			{
				name = "matMULTYardSalvager_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)Texture2D.normalTexture);
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0.35f);
			material.SetColor("_EmColor", Color.white);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			val4.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
			{
				new MeshReplacement
				{
					renderer = (Renderer)(object)target,
					mesh = mesh,
					meshAddress = new AssetReferenceT<Mesh>("")
				}
			};
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinEclipsePlaytest_MULT_E1";
			skin.nameToken = "ECLIPSEPLAYTEST_MULT_E1_YARD_SALVAGER_NAME";
			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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E1_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E1_REGISTERED count=" + additions.Count + " version=0.1.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 == "ToolbotBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E1_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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_0365: 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)) != "MTE1")
		{
			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 != 64)
		{
			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 = "CommandoMULTYardSalvager",
			indexFormat = (IndexFormat)(num > 65535)
		};
		val2.vertices = array2;
		val2.normals = array3;
		val2.uv = array4;
		val2.boneWeights = array5;
		val2.bindposes = reference.bindposes;
		val2.triangles = array8;
		val2.RecalculateBounds();
		val2.RecalculateTangents();
		return AddNativeAlternateTools(val2, reference, renderer);
	}

	private Mesh AddNativeAlternateTools(Mesh authored, Mesh reference, SkinnedMeshRenderer renderer)
	{
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: 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)
		HashSet<int> hashSet = new HashSet<int>();
		for (int i = 0; i < renderer.bones.Length; i++)
		{
			string text = (Object.op_Implicit((Object)(object)renderer.bones[i]) ? ((Object)renderer.bones[i]).name : "");
			if (text.StartsWith("spear", StringComparison.Ordinal) || text.StartsWith("saw", StringComparison.Ordinal) || text.StartsWith("grenade", StringComparison.Ordinal))
			{
				hashSet.Add(i);
			}
		}
		if (hashSet.Count == 0 || !reference.isReadable)
		{
			throw new InvalidDataException("Native alternate-tool geometry unavailable; registration aborted safely.");
		}
		Vector3[] vertices = reference.vertices;
		Vector3[] normals = reference.normals;
		BoneWeight[] boneWeights = reference.boneWeights;
		int[] triangles = reference.triangles;
		if (vertices.Length != boneWeights.Length || normals.Length != vertices.Length)
		{
			throw new InvalidDataException("Native tool mesh arrays differ.");
		}
		List<Vector3> list = new List<Vector3>(authored.vertices);
		List<Vector3> list2 = new List<Vector3>(authored.normals);
		List<Vector2> list3 = new List<Vector2>(authored.uv);
		List<BoneWeight> list4 = new List<BoneWeight>(authored.boneWeights);
		List<int> list5 = new List<int>(authored.triangles);
		Dictionary<int, int> dictionary = new Dictionary<int, int>();
		int num = 0;
		for (int j = 0; j < triangles.Length; j += 3)
		{
			if (!ToolVertex(boneWeights[triangles[j]], hashSet) || !ToolVertex(boneWeights[triangles[j + 1]], hashSet) || !ToolVertex(boneWeights[triangles[j + 2]], hashSet))
			{
				continue;
			}
			for (int k = 0; k < 3; k++)
			{
				int num2 = triangles[j + k];
				if (!dictionary.TryGetValue(num2, out var value))
				{
					value = list.Count;
					dictionary.Add(num2, value);
					list.Add(vertices[num2]);
					list2.Add(normals[num2]);
					list4.Add(boneWeights[num2]);
					list3.Add(new Vector2(0.875f, 0.25f));
				}
				list5.Add(value);
			}
			num++;
		}
		if (num == 0)
		{
			throw new InvalidDataException("No native alternate-tool triangles found.");
		}
		authored.Clear();
		authored.indexFormat = (IndexFormat)(list.Count > 65535);
		authored.SetVertices(list);
		authored.SetNormals(list2);
		authored.SetUVs(0, list3);
		authored.boneWeights = list4.ToArray();
		authored.bindposes = reference.bindposes;
		authored.SetTriangles(list5, 0);
		authored.RecalculateBounds();
		authored.RecalculateTangents();
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_MULT_E1_NATIVE_ALTERNATES triangles=" + num + "; draft steel palette; runtime motion untested"));
		return authored;
	}

	private static bool ToolVertex(BoneWeight w, HashSet<int> ids)
	{
		if ((((BoneWeight)(ref w)).weight0 <= 0f || ids.Contains(((BoneWeight)(ref w)).boneIndex0)) && (((BoneWeight)(ref w)).weight1 <= 0f || ids.Contains(((BoneWeight)(ref w)).boneIndex1)) && (((BoneWeight)(ref w)).weight2 <= 0f || ids.Contains(((BoneWeight)(ref w)).boneIndex2)))
		{
			if (!(((BoneWeight)(ref w)).weight3 <= 0f))
			{
				return ids.Contains(((BoneWeight)(ref w)).boneIndex3);
			}
			return true;
		}
		return false;
	}

	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;
	}
}

BepInEx/plugins/EclipseREXCollection/EclipseREXCollection.dll

Decompiled 3 hours 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 BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.ContentManagement;
using RoR2.UI.MainMenu;
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 EclipseRex;

[BepInPlugin("eclipseplaytest.rex.collection", "REX Eclipse Collection", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class RexCollection : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.rex.collection";

	public const string Version = "0.1.2";

	private static RexCollection instance;

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

	private string folder;

	private GameObject modelPrefab;

	private bool registered;

	private float deadline;

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

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

	private void CheckDeadline()
	{
		if (Time.realtimeSinceStartup > deadline)
		{
			throw new TimeoutException("REX asset loading exceeded deadline; continuing without registration");
		}
	}

	private IEnumerator Register()
	{
		GameObject val = BodyCatalog.FindBodyPrefab("TreebotBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("TreebotBody missing");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (!Object.op_Implicit((Object)(object)controller) || controller.skins.Length == 0)
		{
			throw new InvalidOperationException("REX default skin missing");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipseRexPricklyCustomer"))
		{
			throw new InvalidOperationException("REX E1 already registered");
		}
		SkinDef baseSkin = controller.skins[0];
		SkinDefParams parameters = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)parameters) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retained.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op));
			while (!op.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			parameters = op.Result;
		}
		if (!Object.op_Implicit((Object)(object)parameters))
		{
			throw new InvalidOperationException("REX skin parameters unavailable");
		}
		SkinnedMeshRenderer[] renderers = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == "TreebotBotMesh");
		Mesh reference = target.sharedMesh;
		if (!Object.op_Implicit((Object)(object)reference))
		{
			MeshReplacement val2 = parameters.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
			reference = val2.mesh;
			if (!Object.op_Implicit((Object)(object)reference) && val2.meshAddress != null && ((AssetReference)val2.meshAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retained.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2));
				while (!op2.IsDone)
				{
					CheckDeadline();
					yield return null;
				}
				reference = op2.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)reference) || target.bones.Length != 90 || reference.bindposes.Length != 90)
		{
			throw new InvalidOperationException("REX native rig layout changed");
		}
		RendererInfo originalInfo = parameters.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 && ((AssetReference)originalInfo.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)originalInfo.defaultMaterialAddress).RuntimeKey);
			retained.Add(AsyncOperationHandle<Material>.op_Implicit(op3));
			while (!op3.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			val3 = op3.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("REX native material unavailable");
		}
		RexRigDefinition rexRigDefinition = RexRigDefinition.Read(Path.Combine(folder, "assets", "body.meshbin"), target, reference);
		Material val4 = new Material(val3)
		{
			name = "matEclipseRexPricklyCustomer009"
		};
		Texture2D val5 = new Texture2D(2, 2, (TextureFormat)4, true, false)
		{
			name = "REX original flat palette",
			filterMode = (FilterMode)0,
			wrapMode = (TextureWrapMode)1
		};
		if (!ImageConversion.LoadImage(val5, File.ReadAllBytes(Path.Combine(folder, "assets", "albedo-spec.png")), false))
		{
			throw new InvalidDataException("REX palette failed to decode");
		}
		val4.SetTexture("_MainTex", (Texture)(object)val5);
		val4.SetColor("_Color", Color.white);
		val4.SetFloat("_NormalStrength", 0f);
		val4.SetFloat("_Smoothness", 0.28f);
		val4.SetFloat("_SpecularStrength", 0.5f);
		val4.SetFloat("_SpecularExponent", 8f);
		val4.SetFloat("_EmPower", 0f);
		val4.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		val4.DisableKeyword("LIMBREMOVAL");
		val4.SetFloat("_LimbRemovalOn", 0f);
		val4.DisableKeyword("SPLATMAP");
		val4.SetFloat("_SplatmapOn", 0f);
		val4.DisableKeyword("USE_VERTEX_COLORS");
		val4.SetFloat("_ColorsOn", 0f);
		val4.DisableKeyword("FORCE_SPEC");
		val4.SetFloat("_ForceSpecOn", 0f);
		Mesh mesh = new Mesh
		{
			name = "EclipseRex_EmptyNativeVisual"
		};
		List<MeshReplacement> list = new List<MeshReplacement>
		{
			new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = rexRigDefinition.Mesh,
				meshAddress = new AssetReferenceT<Mesh>("")
			}
		};
		string[] array = new string[3] { "TreebotRootMesh", "TreebotLeafletMesh", "TreebotFlowerMesh" };
		foreach (string name in array)
		{
			SkinnedMeshRenderer renderer = renderers.Single((SkinnedMeshRenderer x) => ((Object)x).name == name);
			list.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)renderer,
				mesh = mesh,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		RendererInfo val6 = originalInfo;
		val6.defaultMaterial = val4;
		val6.defaultMaterialAddress = new AssetReferenceT<Material>("");
		SkinDefParams val7 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val7).name = "paramsEclipseRexPricklyCustomer";
		val7.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val6 };
		val7.meshReplacements = list.ToArray();
		SkinDef val8 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val8).name = "skinEclipseRexPricklyCustomer";
		val8.nameToken = "ECLIPSE_REX_PRICKLY_CUSTOMER_NAME";
		val8.unlockableDef = null;
		val8.rootObject = modelPrefab;
		val8.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val8.skinDefParams = val7;
		val8.icon = Icon();
		LanguageAPI.Add(val8.nameToken, "REX - Prickly Customer (Draft)");
		RexRigDefinition.Registered.Add(rexRigDefinition.Mesh, rexRigDefinition);
		if (!Object.op_Implicit((Object)(object)modelPrefab.GetComponent<RexCosmeticRig>()))
		{
			modelPrefab.AddComponent<RexCosmeticRig>();
		}
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val8 }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSE_REX_REGISTERED collection=0.1.2 members=1 model=009 unlocked=true runtime_validation_pending=true");
	}

	private static Sprite Icon()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//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_0060: 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)
		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++)
			{
				array[i * 64 + j] = ((j < 2 || i < 2 || j > 61 || i > 61) ? new Color32((byte)25, (byte)35, (byte)30, byte.MaxValue) : ((i > 31) ? new Color32((byte)111, (byte)147, (byte)86, byte.MaxValue) : new Color32((byte)184, (byte)116, (byte)75, byte.MaxValue)));
			}
		}
		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 SyncDisplay()
	{
		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 == "TreebotBody"));
		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))
		{
			ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
			val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			if (!Object.op_Implicit((Object)(object)((Component)componentInChildren).GetComponent<RexCosmeticRig>()))
			{
				((Component)componentInChildren).gameObject.AddComponent<RexCosmeticRig>();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSE_REX_DISPLAY_READY skins=" + val2.skins.Length));
		}
	}

	private void OnDestroy()
	{
		RoR2Application.onLoad = (Action)Delegate.Remove(RoR2Application.onLoad, new Action(SyncDisplay));
		MainMenuController.OnMainMenuInitialised -= SyncDisplay;
	}
}
public sealed class RexRigDefinition
{
	public Mesh Mesh;

	public string[] Names;

	public Matrix4x4[] HelperBindposes;

	public static readonly Dictionary<Mesh, RexRigDefinition> Registered = new Dictionary<Mesh, RexRigDefinition>();

	private static float Finite(float x)
	{
		if (float.IsNaN(x) || float.IsInfinity(x))
		{
			throw new InvalidDataException("Nonfinite mesh value");
		}
		return x;
	}

	private static Vector3 Vec(BinaryReader r)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(Finite(r.ReadSingle()), Finite(r.ReadSingle()), Finite(r.ReadSingle()));
	}

	public static RexRigDefinition Read(string path, SkinnedMeshRenderer native, Mesh reference)
	{
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c4: 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_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_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: 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)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0271: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: 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_04e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fc: Expected O, but got Unknown
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_046d: Unknown result type (might be due to invalid IL or missing references)
		//IL_046f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0567: Unknown result type (might be due to invalid IL or missing references)
		//IL_0560: Unknown result type (might be due to invalid IL or missing references)
		//IL_0570: Unknown result type (might be due to invalid IL or missing references)
		//IL_0575: Unknown result type (might be due to invalid IL or missing references)
		//IL_057a: Unknown result type (might be due to invalid IL or missing references)
		//IL_057e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0583: Unknown result type (might be due to invalid IL or missing references)
		//IL_0589: Unknown result type (might be due to invalid IL or missing references)
		//IL_0590: Unknown result type (might be due to invalid IL or missing references)
		//IL_0597: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a8: 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)) != "REX1")
		{
			throw new InvalidDataException("Invalid REX mesh header");
		}
		int num = binaryReader.ReadInt32();
		int num2 = binaryReader.ReadInt32();
		int bc = binaryReader.ReadInt32();
		if (num < 3 || num > 200000 || num2 < 3 || num2 > 1200000 || num2 % 3 != 0 || bc != 100 || native.bones.Length != 90 || reference.bindposes.Length != 90)
		{
			throw new InvalidDataException("Unexpected REX dimensions");
		}
		string[] array = new string[bc];
		for (int i = 0; i < bc; i++)
		{
			int num3 = binaryReader.ReadInt32();
			if (num3 < 1 || num3 > 128)
			{
				throw new InvalidDataException("Bone name length");
			}
			array[i] = new string(binaryReader.ReadChars(num3));
		}
		if (array.Distinct().Count() != bc)
		{
			throw new InvalidDataException("Duplicate bone names");
		}
		Dictionary<string, int> dictionary = native.bones.Select((Transform b, int i2) => new
		{
			b = b,
			i = i2
		}).ToDictionary(x => ((Object)x.b).name, x => x.i);
		Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[bc];
		for (int num4 = 0; num4 < 90; num4++)
		{
			if (!dictionary.TryGetValue(array[num4], out var value))
			{
				throw new InvalidDataException("Native bone missing: " + array[num4]);
			}
			array2[num4] = reference.bindposes[value];
		}
		Matrix4x4[] array3 = (Matrix4x4[])(object)new Matrix4x4[10];
		for (int num5 = 90; num5 < bc; num5++)
		{
			if (!array[num5].StartsWith("REX_"))
			{
				throw new InvalidDataException("Unexpected helper");
			}
			Matrix4x4 val = default(Matrix4x4);
			for (int num6 = 0; num6 < 4; num6++)
			{
				for (int num7 = 0; num7 < 4; num7++)
				{
					((Matrix4x4)(ref val))[num6, num7] = Finite(binaryReader.ReadSingle());
				}
			}
			if ((double)Math.Abs(((Matrix4x4)(ref val)).determinant) < 1E-08)
			{
				throw new InvalidDataException("Singular helper bind");
			}
			array2[num5] = (array3[num5 - 90] = val);
		}
		Vector3[] array4 = (Vector3[])(object)new Vector3[num];
		Vector3[] array5 = (Vector3[])(object)new Vector3[num];
		Vector2[] array6 = (Vector2[])(object)new Vector2[num];
		BoneWeight[] array7 = (BoneWeight[])(object)new BoneWeight[num];
		for (int num8 = 0; num8 < num; num8++)
		{
			array4[num8] = Vec(binaryReader);
			array5[num8] = Vec(binaryReader);
			array6[num8] = new Vector2(Finite(binaryReader.ReadSingle()), Finite(binaryReader.ReadSingle()));
			int[] array8 = new int[4]
			{
				binaryReader.ReadInt32(),
				binaryReader.ReadInt32(),
				binaryReader.ReadInt32(),
				binaryReader.ReadInt32()
			};
			float[] array9 = new float[4]
			{
				Finite(binaryReader.ReadSingle()),
				Finite(binaryReader.ReadSingle()),
				Finite(binaryReader.ReadSingle()),
				Finite(binaryReader.ReadSingle())
			};
			if (array8.Any((int x) => x < 0 || x >= bc) || array9.Any((float x) => x < 0f) || (double)Math.Abs(array9.Sum() - 1f) > 1E-05 || (double)Math.Abs(((Vector3)(ref array5[num8])).magnitude - 1f) > 0.001)
			{
				throw new InvalidDataException("Invalid weights or normal");
			}
			int num9 = num8;
			BoneWeight val2 = default(BoneWeight);
			((BoneWeight)(ref val2)).boneIndex0 = array8[0];
			((BoneWeight)(ref val2)).boneIndex1 = array8[1];
			((BoneWeight)(ref val2)).boneIndex2 = array8[2];
			((BoneWeight)(ref val2)).boneIndex3 = array8[3];
			((BoneWeight)(ref val2)).weight0 = array9[0];
			((BoneWeight)(ref val2)).weight1 = array9[1];
			((BoneWeight)(ref val2)).weight2 = array9[2];
			((BoneWeight)(ref val2)).weight3 = array9[3];
			array7[num9] = val2;
		}
		int[] array10 = new int[num2];
		for (int num10 = 0; num10 < num2; num10++)
		{
			array10[num10] = binaryReader.ReadInt32();
			if (array10[num10] < 0 || array10[num10] >= num)
			{
				throw new InvalidDataException("Triangle index");
			}
		}
		if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
		{
			throw new InvalidDataException("Trailing mesh bytes");
		}
		Mesh val3 = new Mesh
		{
			name = "EclipseRex_PricklyCustomer_009",
			indexFormat = (IndexFormat)1
		};
		val3.vertices = array4;
		val3.normals = array5;
		val3.uv = array6;
		val3.boneWeights = array7;
		val3.bindposes = array2;
		val3.triangles = array10;
		val3.RecalculateBounds();
		Vector4[] array11 = (Vector4[])(object)new Vector4[num];
		for (int num11 = 0; num11 < num; num11++)
		{
			Vector3 val4 = Vector3.Cross((Mathf.Abs(array5[num11].y) > 0.99f) ? Vector3.right : Vector3.up, array5[num11]);
			Vector3 normalized = ((Vector3)(ref val4)).normalized;
			array11[num11] = new Vector4(normalized.x, normalized.y, normalized.z, 1f);
		}
		val3.tangents = array11;
		return new RexRigDefinition
		{
			Mesh = val3,
			Names = array,
			HelperBindposes = array3
		};
	}
}
[DefaultExecutionOrder(32000)]
public sealed class RexCosmeticRig : MonoBehaviour
{
	private SkinnedMeshRenderer target;

	private Transform[] originalBones;

	private Transform[] customBones;

	private Bounds originalBounds;

	private bool originalUpdateOffscreen;

	private bool active;

	private bool failed;

	private GameObject container;

	private RexRigDefinition definition;

	private RexPoseSolver solver;

	private M4 authorToRenderer;

	private Dictionary<string, Transform> drivers;

	private Dictionary<string, Transform> helpers;

	private static readonly string[] DriverNames = new string[6] { "ROOT", "PlatformBase", "FlowerBase", "Foot.Front.l", "Foot.Front.r", "Foot.Back.r" };

	public static M4 Read(Matrix4x4 m)
	{
		double[] array = new double[16];
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				array[i * 4 + j] = ((Matrix4x4)(ref m))[i, j];
			}
		}
		return new M4(array);
	}

	private static Matrix4x4 Unity(M4 m)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		Matrix4x4 result = default(Matrix4x4);
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				double num = m[i, j];
				if (double.IsNaN(num) || double.IsInfinity(num))
				{
					throw new InvalidOperationException("Nonfinite cosmetic pose");
				}
				((Matrix4x4)(ref result))[i, j] = (float)num;
			}
		}
		return result;
	}

	private void Initialize(RexRigDefinition d)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Expected O, but got Unknown
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: 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)
		definition = d;
		originalBones = target.bones;
		originalBounds = ((Renderer)target).localBounds;
		originalUpdateOffscreen = target.updateWhenOffscreen;
		if (originalBones.Length != 90)
		{
			throw new InvalidOperationException("REX renderer already has an unexpected bone layout");
		}
		Dictionary<string, Transform> byName = originalBones.ToDictionary((Transform b) => ((Object)b).name, (Transform b) => b);
		drivers = DriverNames.ToDictionary((string n) => n, (string n) => byName[n]);
		container = new GameObject("EclipseREX_CosmeticHelpers");
		container.transform.SetParent(((Component)target).transform, false);
		helpers = new Dictionary<string, Transform>();
		customBones = (Transform[])(object)new Transform[100];
		for (int num = 0; num < 90; num++)
		{
			customBones[num] = byName[d.Names[num]];
		}
		for (int num2 = 90; num2 < 100; num2++)
		{
			Transform transform = new GameObject(d.Names[num2]).transform;
			string text = d.Names[num2];
			Transform val = container.transform;
			if (text == "REX_Plant")
			{
				val = drivers["FlowerBase"];
			}
			else if (text.EndsWith("_Foot"))
			{
				string text2 = text.Split('_')[2];
				val = drivers[(text2 == "FrontL") ? "Foot.Front.l" : ((text2 == "FrontR") ? "Foot.Front.r" : "Foot.Back.r")];
			}
			transform.SetParent(val, false);
			helpers.Add(text, transform);
			customBones[num2] = transform;
		}
		solver = RexRigConfig.Build();
		authorToRenderer = RexRigConfig.RendererToAuthor.Inverse();
		ApplyPose();
		target.bones = customBones;
		((Renderer)target).localBounds = new Bounds(new Vector3(0f, 3f, 0f), new Vector3(32f, 32f, 32f));
		target.updateWhenOffscreen = true;
		active = true;
	}

	private void ApplyPose()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: 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)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: 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_0127: 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_014d: 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_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: 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_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: 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_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: 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_01c9: Unknown result type (might be due to invalid IL or missing references)
		Dictionary<string, M4> dictionary = new Dictionary<string, M4>();
		M4 m = RexRigConfig.RendererToAuthor * Read(((Component)target).transform.worldToLocalMatrix);
		foreach (KeyValuePair<string, Transform> driver in drivers)
		{
			dictionary.Add(driver.Key, m * Read(driver.Value.localToWorldMatrix));
		}
		double[] reachErrors;
		Vector3 val2 = default(Vector3);
		foreach (KeyValuePair<string, M4> item in solver.Solve(dictionary, out reachErrors))
		{
			Transform obj = helpers[item.Key];
			Matrix4x4 val = obj.parent.worldToLocalMatrix * ((Component)target).transform.localToWorldMatrix * Unity(authorToRenderer * item.Value);
			Vector4 column = ((Matrix4x4)(ref val)).GetColumn(0);
			float magnitude = ((Vector4)(ref column)).magnitude;
			column = ((Matrix4x4)(ref val)).GetColumn(1);
			float magnitude2 = ((Vector4)(ref column)).magnitude;
			column = ((Matrix4x4)(ref val)).GetColumn(2);
			((Vector3)(ref val2))..ctor(magnitude, magnitude2, ((Vector4)(ref column)).magnitude);
			if ((double)val2.x < 1E-06 || (double)val2.y < 1E-06 || (double)val2.z < 1E-06 || ((Matrix4x4)(ref val)).determinant <= 0f)
			{
				throw new InvalidOperationException("Invalid cosmetic pose scale");
			}
			obj.localPosition = Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(3));
			obj.localRotation = Quaternion.LookRotation(Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(2) / val2.z), Vector4.op_Implicit(((Matrix4x4)(ref val)).GetColumn(1) / val2.y));
			obj.localScale = val2;
		}
	}

	private void LateUpdate()
	{
		if (failed)
		{
			return;
		}
		try
		{
			if (!Object.op_Implicit((Object)(object)target))
			{
				target = ((IEnumerable<SkinnedMeshRenderer>)((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true)).SingleOrDefault((Func<SkinnedMeshRenderer, bool>)((SkinnedMeshRenderer r) => ((Object)r).name == "TreebotBotMesh"));
			}
			if (Object.op_Implicit((Object)(object)target))
			{
				if (!Object.op_Implicit((Object)(object)target.sharedMesh) || !RexRigDefinition.Registered.TryGetValue(target.sharedMesh, out var value))
				{
					Restore();
				}
				else if (!active)
				{
					Initialize(value);
				}
				else if (definition != value)
				{
					Restore();
					Initialize(value);
				}
				else
				{
					ApplyPose();
				}
			}
		}
		catch (Exception ex)
		{
			failed = true;
			Debug.LogError((object)("ECLIPSE_REX_RIG_FAILED: " + ex));
			Restore();
			ModelSkinController component = ((Component)this).GetComponent<ModelSkinController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				((MonoBehaviour)this).StartCoroutine(component.ApplySkinAsync(0, (AsyncReferenceHandleUnloadType)3));
			}
		}
	}

	private void Restore()
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		if (Object.op_Implicit((Object)(object)target) && originalBones != null)
		{
			target.bones = originalBones;
			((Renderer)target).localBounds = originalBounds;
			target.updateWhenOffscreen = originalUpdateOffscreen;
		}
		if (helpers != null)
		{
			foreach (Transform value in helpers.Values)
			{
				if (Object.op_Implicit((Object)(object)value))
				{
					Object.Destroy((Object)(object)((Component)value).gameObject);
				}
			}
		}
		if (Object.op_Implicit((Object)(object)container))
		{
			Object.Destroy((Object)(object)container);
		}
		container = null;
		customBones = null;
		helpers = null;
		drivers = null;
		originalBones = null;
		definition = null;
		active = false;
	}

	private void OnDisable()
	{
		Restore();
	}

	private void OnDestroy()
	{
		Restore();
	}
}
public struct V3
{
	public double x;

	public double y;

	public double z;

	public double Length => Math.Sqrt(x * x + y * y + z * z);

	public V3(double x, double y, double z)
	{
		this.x = x;
		this.y = y;
		this.z = z;
	}

	public static V3 operator +(V3 a, V3 b)
	{
		return new V3(a.x + b.x, a.y + b.y, a.z + b.z);
	}

	public static V3 operator -(V3 a, V3 b)
	{
		return new V3(a.x - b.x, a.y - b.y, a.z - b.z);
	}

	public static V3 operator *(V3 a, double s)
	{
		return new V3(a.x * s, a.y * s, a.z * s);
	}

	public V3 Unit()
	{
		double length = Length;
		if (length < 1E-10)
		{
			throw new InvalidOperationException("Zero pose direction");
		}
		return this * (1.0 / length);
	}

	public static double Dot(V3 a, V3 b)
	{
		return a.x * b.x + a.y * b.y + a.z * b.z;
	}

	public static V3 Cross(V3 a, V3 b)
	{
		return new V3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
	}
}
public sealed class M4
{
	public readonly double[] v;

	public double this[int r, int c]
	{
		get
		{
			return v[r * 4 + c];
		}
		set
		{
			v[r * 4 + c] = value;
		}
	}

	public V3 Translation
	{
		get
		{
			return new V3(v[3], v[7], v[11]);
		}
		set
		{
			v[3] = value.x;
			v[7] = value.y;
			v[11] = value.z;
		}
	}

	public M4()
	{
		v = new double[16];
		v[0] = (v[5] = (v[10] = (v[15] = 1.0)));
	}

	public M4(double[] values)
	{
		if (values.Length != 16)
		{
			throw new ArgumentException();
		}
		v = (double[])values.Clone();
	}

	public V3 Point(V3 p)
	{
		return new V3(v[0] * p.x + v[1] * p.y + v[2] * p.z + v[3], v[4] * p.x + v[5] * p.y + v[6] * p.z + v[7], v[8] * p.x + v[9] * p.y + v[10] * p.z + v[11]);
	}

	public V3 Direction(V3 p)
	{
		return new V3(v[0] * p.x + v[1] * p.y + v[2] * p.z, v[4] * p.x + v[5] * p.y + v[6] * p.z, v[8] * p.x + v[9] * p.y + v[10] * p.z);
	}

	public M4 Rotation()
	{
		return new M4(v)
		{
			Translation = default(V3)
		};
	}

	public static M4 operator *(M4 a, M4 b)
	{
		M4 m = new M4();
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				double num = 0.0;
				for (int k = 0; k < 4; k++)
				{
					num += a[i, k] * b[k, j];
				}
				m[i, j] = num;
			}
		}
		return m;
	}

	public M4 Inverse()
	{
		double[,] array = new double[4, 8];
		for (int i = 0; i < 4; i++)
		{
			for (int j = 0; j < 4; j++)
			{
				array[i, j] = this[i, j];
				array[i, j + 4] = ((i == j) ? 1 : 0);
			}
		}
		for (int k = 0; k < 4; k++)
		{
			int num = k;
			for (int l = k + 1; l < 4; l++)
			{
				if (Math.Abs(array[l, k]) > Math.Abs(array[num, k]))
				{
					num = l;
				}
			}
			if (Math.Abs(array[num, k]) < 1E-12)
			{
				throw new InvalidOperationException("Singular pose matrix");
			}
			for (int m = 0; m < 8; m++)
			{
				double num2 = array[k, m];
				array[k, m] = array[num, m];
				array[num, m] = num2;
			}
			double num3 = array[k, k];
			for (int n = 0; n < 8; n++)
			{
				array[k, n] /= num3;
			}
			for (int num4 = 0; num4 < 4; num4++)
			{
				if (num4 != k)
				{
					double num5 = array[num4, k];
					for (int num6 = 0; num6 < 8; num6++)
					{
						array[num4, num6] -= num5 * array[k, num6];
					}
				}
			}
		}
		M4 m2 = new M4();
		for (int num7 = 0; num7 < 4; num7++)
		{
			for (int num8 = 0; num8 < 4; num8++)
			{
				m2[num7, num8] = array[num7, num8 + 4];
			}
		}
		return m2;
	}

	public static M4 Align(V3 a, V3 b)
	{
		a = a.Unit();
		b = b.Unit();
		double num = Math.Max(-1.0, Math.Min(1.0, V3.Dot(a, b)));
		M4 m = new M4();
		if (num > 0.999999999)
		{
			return m;
		}
		if (num < -0.999999999)
		{
			V3 v = V3.Cross(a, (Math.Abs(a.x) < 0.8) ? new V3(1.0, 0.0, 0.0) : new V3(0.0, 1.0, 0.0)).Unit();
			double[] array = new double[3] { v.x, v.y, v.z };
			for (int i = 0; i < 3; i++)
			{
				for (int j = 0; j < 3; j++)
				{
					m[i, j] = 2.0 * array[i] * array[j] - (double)((i == j) ? 1 : 0);
				}
			}
			return m;
		}
		V3 v2 = V3.Cross(a, b);
		double[,] array2 = new double[3, 3]
		{
			{
				0.0,
				0.0 - v2.z,
				v2.y
			},
			{
				v2.z,
				0.0,
				0.0 - v2.x
			},
			{
				0.0 - v2.y,
				v2.x,
				0.0
			}
		};
		for (int k = 0; k < 3; k++)
		{
			for (int l = 0; l < 3; l++)
			{
				double num2 = 0.0;
				for (int n = 0; n < 3; n++)
				{
					num2 += array2[k, n] * array2[n, l];
				}
				m[k, l] = (double)((k == l) ? 1 : 0) + array2[k, l] + num2 / (1.0 + num);
			}
		}
		return m;
	}
}
public sealed class RexPoseSolver
{
	public sealed class Leg
	{
		public string Label;

		public string Driver;

		public V3 Hip;

		public V3 Knee;

		public V3 Foot;

		public V3 ContactLocal;

		public V3 ContactIdle;

		public M4 UpperRest;

		public M4 LowerRest;

		public M4 FootRest;

		public M4 IdleDriverInverse;
	}

	public readonly Leg[] Legs;

	private readonly M4 rootBindInverse;

	private readonly M4 platformBindInverse;

	private readonly M4 plantCorrection;

	public RexPoseSolver(Leg[] legs, M4 rootBind, M4 platformBind, M4 idlePlatform, M4 idleFlower, M4 plantRest)
	{
		Legs = legs;
		rootBindInverse = rootBind.Inverse();
		platformBindInverse = platformBind.Inverse();
		plantCorrection = (idlePlatform.Inverse() * idleFlower).Inverse() * platformBindInverse * plantRest;
	}

	public Dictionary<string, M4> Solve(Dictionary<string, M4> native, out double[] reachErrors)
	{
		M4 m = native["ROOT"] * rootBindInverse;
		M4 m2 = native["PlatformBase"] * platformBindInverse;
		M4 m3 = m.Inverse();
		Dictionary<string, M4> dictionary = new Dictionary<string, M4>();
		reachErrors = new double[Legs.Length];
		for (int i = 0; i < Legs.Length; i++)
		{
			Leg leg = Legs[i];
			V3 v = m2.Point(leg.Hip);
			M4 m4 = native[leg.Driver];
			V3 v2 = m3.Point(m4.Point(leg.ContactLocal)) - leg.ContactIdle;
			if (leg.Label == "RearC")
			{
				v2.x = 0.0;
			}
			v2.x *= 0.55;
			v2.y *= 0.55;
			V3 v3 = m.Point(leg.Foot + v2) - v;
			double length = v3.Length;
			V3 v4 = v3.Unit();
			double length2 = (leg.Knee - leg.Hip).Length;
			double length3 = (leg.Foot - leg.Knee).Length;
			double num = Math.Max(Math.Abs(length2 - length3) + 1E-05, Math.Min(length2 + length3 - 1E-05, length));
			reachErrors[i] = Math.Abs(length - num);
			V3 v5 = v + v4 * num;
			double num2 = (length2 * length2 - length3 * length3 + num * num) / (2.0 * num);
			double num3 = Math.Sqrt(Math.Max(0.0, length2 * length2 - num2 * num2));
			V3 a = m.Direction(new V3(leg.Foot.x - leg.Hip.x, leg.Foot.y - leg.Hip.y, 0.0));
			a -= v4 * V3.Dot(a, v4);
			if (a.Length < 1E-08)
			{
				a = V3.Cross(v4, new V3(0.0, 0.0, 1.0));
			}
			V3 v6 = v + v4 * num2 + a.Unit() * num3;
			M4 m5 = M4.Align(leg.Knee - leg.Hip, v6 - v) * leg.UpperRest.Rotation();
			m5.Translation = v;
			M4 m6 = M4.Align(leg.Foot - leg.Knee, v5 - v6) * leg.LowerRest.Rotation();
			m6.Translation = v6;
			M4 m7 = m4.Rotation() * leg.IdleDriverInverse * leg.FootRest.Rotation();
			m7.Translation = v5;
			string text = "REX_Tripod_" + leg.Label + "_";
			dictionary.Add(text + "Upper", m5);
			dictionary.Add(text + "Lower", m6);
			dictionary.Add(text + "Foot", m7);
		}
		dictionary.Add("REX_Plant", native["FlowerBase"] * plantCorrection);
		return dictionary;
	}
}
public static class RexRigConfig
{
	public static readonly M4 RendererToAuthor = new M4(new double[16]
	{
		0.5, 0.0, 0.0, 0.0, 0.0, 0.49999998288572556, 6.717942824252532E-08, 0.0, 0.0, -6.717942824252532E-08,
		0.49999998288572556, 0.800000011920929, 0.0, 0.0, 0.0, 1.0
	});

	public static RexPoseSolver Build()
	{
		return new RexPoseSolver(new RexPoseSolver.Leg[3]
		{
			new RexPoseSolver.Leg
			{
				Label = "FrontL",
				Driver = "Foot.Front.l",
				Hip = new V3(-0.53, -0.5, 1.79),
				Knee = new V3(-0.99, -0.94, 1.1),
				Foot = new V3(-1.39, -1.39, 0.14),
				ContactLocal = new V3(-1.3846563284847235E-07, 1.5331812713846993, 0.020047935785438287),
				ContactIdle = new V3(-1.0058862908697492, -1.0058871240795575, 0.01943790492028058),
				UpperRest = new M4(new double[16]
				{
					0.5480934772696795, 0.6778596728878948, -0.4899999521798719, -0.5299999713897705, 0.4899998920769537, -0.7349998499448206, -0.4686956442532235, -0.5, -0.6778596355269357, 0.016789123524324042,
					-0.734999722257399, 1.7899999618530273, 0.0, 0.0, 0.0, 1.0
				}),
				LowerRest = new M4(new double[16]
				{
					0.7933266407317046, 0.49601616597604353, -0.3529885261317727, -0.9900000095367432, 0.3529884610987928, -0.8471727037684982, -0.39711214496745484, -0.9399999976158142, -0.4960161531268543, 0.1904388084012335,
					-0.8471725756805828, 1.100000023841858, 0.0, 0.0, 0.0, 1.0
				}),
				FootRest = new M4(new double[16]
				{
					0.9999999880826637, 4.1418082164277474E-08, 5.111020528055165E-08, -1.3900001350115787, 1.2210625252571675E-07, 0.9999999981696062, -8.931780216662775E-08, -1.390000048804431, -8.195324128611039E-08, 1.0209338942114178E-07,
					1.000000092685953, 0.14000016151088834, 0.0, 0.0, 0.0, 1.0
				}),
				IdleDriverInverse = new M4(new double[16]
				{
					0.70710650838484, -0.7071070543604773, 6.845061881888073E-07, -1.29012894087189E-06, 0.09226262681726324, 0.09226159652320774, -0.9914514621269739, 1.7380634741034313, 0.7010624682441953, 0.7010620531261419,
					0.13047836821247746, 1.4278901279404805, 0.0, 0.0, 0.0, 1.0
				}).Rotation()
			},
			new RexPoseSolver.Leg
			{
				Label = "FrontR",
				Driver = "Foot.Front.r",
				Hip = new V3(0.53, -0.5, 1.79),
				Knee = new V3(0.99, -0.94, 1.1),
				Foot = new V3(1.39, -1.39, 0.14),
				ContactLocal = new V3(1.1543029176941388E-07, 1.5331812079728975, 0.020047764865803175),
				ContactIdle = new V3(1.0058873793248644, -1.0058862281441765, 0.019437533244369077),
				UpperRest = new M4(new double[16]
				{
					0.5480934772696795, -0.6778596728878948, 0.4899999521798719, 0.5299999713897705, -0.4899998920769537, -0.7349998499448206, -0.4686956442532235, -0.5, 0.6778596355269357, 0.016789123524324042,
					-0.734999722257399, 1.7899999618530273, 0.0, 0.0, 0.0, 1.0
				}),
				LowerRest = new M4(new double[16]
				{
					0.7933266407317046, -0.49601616597604353, 0.3529885261317727, 0.9900000095367432, -0.3529884610987928, -0.8471727037684982, -0.39711214496745484, -0.9399999976158142, 0.4960161531268543, 0.1904388084012335,
					-0.8471725756805828, 1.100000023841858, 0.0, 0.0, 0.0, 1.0
				}),
				FootRest = new M4(new double[16]
				{
					0.9999998724511271, -2.723691648566571E-07, -5.644415250605675E-08, 1.3900002095439161, -2.873006496068035E-09, 0.9999999346513473, -5.571321661698358E-08, -1.3899996673247847, 1.1205359677635479E-07, 7.874737840450729E-08,
					1.0000000820915216, 0.14000045866865443, 0.0, 0.0, 0.0, 1.0
				}),
				IdleDriverInverse = new M4(new double[16]
				{
					0.7071066874816531, 0.7071069592644403, 1.8718868285259177E-07, -4.288331949345071E-07, -0.09226175849103574, 0.09226198519819152, -0.9914512662410887, 1.7380625736731845, -0.7010622746315261, 0.7010619704507328,
					0.1304780288614005, 1.4278898691667963, 0.0, 0.0, 0.0, 1.0
				}).Rotation()
			},
			new RexPoseSolver.Leg
			{
				Label = "RearC",
				Driver = "Foot.Back.r",
				Hip = new V3(0.0, 0.69, 1.79),
				Knee = new V3(0.0, 1.17, 1.06),
				Foot = new V3(0.0, 1.66, 0.14),
				ContactLocal = new V3(1.4879629994801746E-07, 1.5331807973809892, 0.020047576355472163),
				ContactIdle = new V3(1.0058864786589496, 1.0058876307904365, 0.019438154801437277),
				UpperRest = new M4(new double[16]
				{
					1.0, 0.0, 0.0, 0.0, 0.0, -0.8355556535541666, 0.5494061536433534, 0.6899999976158142, 0.0, -0.5494061536433534,
					-0.8355556535541666, 1.7899999618530273, 0.0, 0.0, 0.0, 1.0
				}),
				LowerRest = new M4(new double[16]
				{
					1.0, 0.0, 0.0, 0.0, 0.0, -0.88261841915849, 0.4700902219161698, 1.1699999570846558, 0.0, -0.4700902219161698,
					-0.88261841915849, 1.059999942779541, 0.0, 0.0, 0.0, 1.0
				}),
				FootRest = new M4(new double[16]
				{
					1.0000003908936435, -7.136207481666075E-09, -7.391923590845879E-08, 2.4502752049571086E-08, 9.036258537493973E-09, 1.0000001201469848, -9.947133293662601E-09, 1.6600002436209893, 8.195272362286263E-08, 2.9341619675920344E-08,
					1.0000000148089307, 0.13999985501268236, 0.0, 0.0, 0.0, 1.0
				}),
				IdleDriverInverse = new M4(new double[16]
				{
					-0.7071071788333751, 0.7071064679124435, 1.1465437935954844E-07, 4.6993756887227234E-08, -0.09226182894182748, -0.09226176059782087, -0.991451352348117, 1.7380626722552521, -0.7010613220499071, -0.7010620491832655,
					0.13047806704847514, 1.4278890717408037, 0.0, 0.0, 0.0, 1.0
				}).Rotation()
			}
		}, new M4(new double[16]
		{
			1.0, 2.9015241340125007E-35, 6.899199907119818E-14, -4.7344911990864204E-08, 6.899199670970217E-14, 1.343588707571352E-07, -0.9999999657714511, -2.8461159122730225E-07, -9.269687086483507E-21, 0.9999999657714511,
			1.343588707571352E-07, -3.2221779466823364E-08, 0.0, 0.0, 0.0, 1.0
		}), new M4(new double[16]
		{
			1.0, -2.842170943040499E-14, 6.890792596898511E-14, -4.734491106891288E-08, 6.890792742907598E-14, 1.343588707571352E-07, -0.9999999657714511, -9.667778579550232E-08, 2.8421699199179017E-14, 0.9999999657714511,
			1.343588707571352E-07, 1.767561819813769, 0.0, 0.0, 0.0, 1.0
		}), new M4(new double[16]
		{
			1.0, 0.0, 0.0, 3.7E-08, 0.0, 0.0, -1.0, -8.9E-08, 0.0, 1.0,
			0.0, 1.181762759, 0.0, 0.0, 0.0, 1.0
		}), new M4(new double[16]
		{
			1.0, 0.0, 0.0, 3.7E-08, 0.0, 0.0, -1.0, -8.9E-08, 0.0, 1.0,
			0.0, 1.913594071, 0.0, 0.0, 0.0, 1.0
		}), new M4(new double[16]
		{
			0.9999999999999998, -1.514973558280571E-08, -2.329304008677558E-15, -4.7344932355375204E-08, 1.5149745919533347E-08, 0.9999999315429223, 1.2678422072511178E-07, -8.860436817607083E-08, -1.0965268978931913E-14, -1.2678422059096674E-07,
			0.9999999315429223, 2.0062991007999553, 0.0, 0.0, 0.0, 1.0
		}));
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/ActionFigurePlaytest/ActionFigurePlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE5;

[BepInPlugin("eclipseplaytest.commando.e5", "Action Figure Playtest", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ActionFigurePlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e5";

	public const string Version = "0.1.1";

	private static ActionFigurePlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(ActionFigurePlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E5_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E5_REGISTRATION_BEGIN async loader 0.1.1");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE5"))
		{
			throw new InvalidOperationException("Action Figure already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE5_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE5"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE5_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE5";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE5";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E5_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Action Figure (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E5_REGISTERED count=1 revision=004 unlocked=true version=0.1.1");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E5_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoActionFigurePlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/ClockworkInfantryPlaytest/ClockworkInfantryPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE4;

[BepInPlugin("eclipseplaytest.commando.e4", "Clockwork Infantry Playtest", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ClockworkInfantryPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e4";

	public const string Version = "0.1.1";

	private static ClockworkInfantryPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(ClockworkInfantryPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E4_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E4_REGISTRATION_BEGIN async loader 0.1.1");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE4"))
		{
			throw new InvalidOperationException("Clockwork Infantry already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE4_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE4"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE4_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE4";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE4";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E4_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Clockwork Infantry (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E4_REGISTERED count=1 revision=002 unlocked=true version=0.1.1");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E4_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoClockworkInfantryPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/ExpeditionMarshalPlaytest/ExpeditionMarshalPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE3;

[BepInPlugin("eclipseplaytest.commando.e3", "Expedition Marshal Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ExpeditionMarshalPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e3";

	public const string Version = "0.1.2";

	private static ExpeditionMarshalPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(ExpeditionMarshalPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E3_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E3_REGISTRATION_BEGIN async loader 0.1.2");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE3"))
		{
			throw new InvalidOperationException("Expedition Marshal already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE3_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE3"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE3_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE3";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE3";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E3_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Expedition Marshal (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E3_REGISTERED count=1 revision=004 unlocked=true version=0.1.2");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E3_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoExpeditionMarshalPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/ExtinctionProtocolPlaytest/ExtinctionProtocolPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE8;

[BepInPlugin("eclipseplaytest.commando.e8", "Extinction Protocol Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class ExtinctionProtocolPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e8";

	public const string Version = "0.1.2";

	private static ExtinctionProtocolPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(ExtinctionProtocolPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E8_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E8_REGISTRATION_BEGIN async loader 0.1.2");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE8"))
		{
			throw new InvalidOperationException("Extinction Protocol already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE8_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE8"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE8_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE8";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE8";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E8_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Extinction Protocol (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E8_REGISTERED count=1 revision=004 unlocked=true version=0.1.2");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E8_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoExtinctionProtocolPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/FrontierRecruitPlaytest/FrontierRecruitPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE1;

[BepInPlugin("eclipseplaytest.commando.e1", "Frontier Recruit Playtest", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class FrontierRecruitPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e1";

	public const string Version = "0.1.1";

	private static FrontierRecruitPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(FrontierRecruitPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E1_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E1_REGISTRATION_BEGIN async loader 0.1.1");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE1"))
		{
			throw new InvalidOperationException("Frontier Recruit already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE1_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE1"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE1_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE1";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE1";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E1_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Frontier Recruit (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E1_REGISTERED count=1 revision=007 unlocked=true version=0.1.1");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E1_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoFrontierRecruitPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/OneManBandPlaytest/OneManBandPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE7;

[BepInPlugin("eclipseplaytest.commando.e7", "One-Man Band Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class OneManBandPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e7";

	public const string Version = "0.1.2";

	private static OneManBandPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(OneManBandPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E7_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E7_REGISTRATION_BEGIN async loader 0.1.2");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE7"))
		{
			throw new InvalidOperationException("One-Man Band already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE7_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE7"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE7_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE7";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE7";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E7_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - One-Man Band (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E7_REGISTERED count=1 revision=004 unlocked=true version=0.1.2");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E7_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoOneManBandPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/QuartermasterPlaytest/QuartermasterPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE6;

[BepInPlugin("eclipseplaytest.commando.e6", "Quartermaster Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class QuartermasterPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e6";

	public const string Version = "0.1.2";

	private static QuartermasterPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(QuartermasterPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E6_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E6_REGISTRATION_BEGIN async loader 0.1.2");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE6"))
		{
			throw new InvalidOperationException("Quartermaster already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE6_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE6"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE6_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE6";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE6";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E6_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Quartermaster (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E6_REGISTERED count=1 revision=003 unlocked=true version=0.1.2");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E6_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoQuartermasterPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Commando_Skins_Playtest/VacuumBreacherPlaytest/VacuumBreacherPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestCommandoE2;

[BepInPlugin("eclipseplaytest.commando.e2", "Vacuum Breacher Playtest", "0.1.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class VacuumBreacherPlaytest : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.commando.e2";

	public const string Version = "0.1.1";

	private static VacuumBreacherPlaytest 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 void Awake()
	{
		folder = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location);
		instance = this;
		SystemInitializerInjector.InjectDependency(typeof(SkinCatalog), typeof(VacuumBreacherPlaytest));
		RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(SyncDisplaySkins));
		MainMenuController.OnMainMenuInitialised += SyncDisplaySkins;
	}

	[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)("ECLIPSEPLAYTEST_COMMANDO_E2_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E2_REGISTRATION_BEGIN async loader 0.1.1");
		GameObject val = BodyCatalog.FindBodyPrefab("CommandoBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("CommandoBody 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("Commando's base skin parameters are unavailable.");
		}
		SkinnedMeshRenderer[] componentsInChildren = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		SkinnedMeshRenderer target = componentsInChildren.First((SkinnedMeshRenderer r) => r.bones.Length == 78 && r.bones.Any((Transform b) => Object.op_Implicit((Object)(object)b) && ((Object)b).name == "head"));
		rendererIndex = Array.IndexOf(componentsInChildren, 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 Commando 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("Commando's game shader is unavailable.");
		}
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinEclipsePlaytestCommandoE2"))
		{
			throw new InvalidOperationException("Vacuum Breacher already registered.");
		}
		mesh = ReadMesh(Path.Combine(folder, "assets", "body.meshbin"), target, referenceMesh);
		((Object)mesh).name = "EclipsePlaytestCommandoE2_Body";
		material = new Material(val3)
		{
			name = "matEclipsePlaytestCommandoE2"
		};
		material.SetTexture("_MainTex", (Texture)(object)ReadTexture("assets/albedo-spec.png", linear: false));
		material.SetTexture("_NormalTex", (Texture)(object)ReadTexture("assets/normal.png", linear: true));
		material.SetColor("_Color", Color.white);
		material.SetFloat("_NormalStrength", 0.5f);
		material.SetFloat("_Smoothness", 0.28f);
		material.SetFloat("_SpecularStrength", 0.5f);
		material.SetFloat("_SpecularExponent", 8f);
		material.SetFloat("_EmPower", 0f);
		material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		material.DisableKeyword("LIMBREMOVAL");
		material.SetFloat("_LimbRemovalOn", 0f);
		List<RendererInfo> list = new List<RendererInfo>();
		List<MeshReplacement> list2 = new List<MeshReplacement>();
		RendererInfo item = originalInfo;
		item.defaultMaterial = material;
		item.defaultMaterialAddress = new AssetReferenceT<Material>("");
		list.Add(item);
		list2.Add(new MeshReplacement
		{
			renderer = (Renderer)(object)target,
			mesh = mesh,
			meshAddress = new AssetReferenceT<Mesh>("")
		});
		string[] array = new string[2] { "l", "r" };
		foreach (string side in array)
		{
			MeshRenderer gun = modelPrefab.GetComponentsInChildren<MeshRenderer>(true).Single((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).transform.parent) && ((Object)((Component)r).transform.parent).name == "gun." + side);
			if (!Object.op_Implicit((Object)(object)((Component)gun).GetComponent<MeshFilter>()))
			{
				throw new InvalidOperationException("Native pistol MeshFilter missing.");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, "assets", "pistol-" + side + ".meshbin"), target, referenceMesh);
			((Object)val4).name = "EclipsePlaytestCommandoE2_Pistol_" + side;
			RendererInfo item2 = baseParams.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)gun);
			item2.defaultMaterial = material;
			item2.defaultMaterialAddress = new AssetReferenceT<Material>("");
			list.Add(item2);
			list2.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)gun,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
		}
		SkinDefParams val5 = ScriptableObject.CreateInstance<SkinDefParams>();
		((Object)val5).name = "paramsEclipsePlaytestCommandoE2";
		val5.rendererInfos = list.ToArray();
		val5.meshReplacements = list2.ToArray();
		skin = ScriptableObject.CreateInstance<SkinDef>();
		((Object)skin).name = "skinEclipsePlaytestCommandoE2";
		skin.nameToken = "ECLIPSEPLAYTEST_COMMANDO_E2_NAME";
		LanguageAPI.Add(skin.nameToken, "Commando - Vacuum Breacher (Playtest)");
		skin.icon = CreateIcon((Color32[])(object)new Color32[4]
		{
			new Color32((byte)187, (byte)154, (byte)100, byte.MaxValue),
			new Color32((byte)58, (byte)66, (byte)65, byte.MaxValue),
			new Color32((byte)202, (byte)175, (byte)126, byte.MaxValue),
			new Color32((byte)40, (byte)45, (byte)49, byte.MaxValue)
		});
		skin.unlockableDef = null;
		skin.rootObject = modelPrefab;
		skin.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		skin.skinDefParams = val5;
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { skin }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_COMMANDO_E2_REGISTERED count=1 revision=003 unlocked=true version=0.1.1");
	}

	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 == "CommandoBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_COMMANDO_E2_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 78)
		{
			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 = "CommandoVacuumBreacherPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Engineer_Skins_Playtest/Local-Engineer_Mine_Surveyor_Playtest/EngineerMineSurveyor.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using EntityStates;
using EntityStates.Engi.EngiWeapon;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Projectile;
using RoR2.UI.MainMenu;
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 EngineerMineSurveyorPlaytest;

[BepInPlugin("eclipseplaytest.engineer.e2", "Engineer - Mine Surveyor (Playtest)", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class EngineerMineSurveyor : BaseUnityPlugin
{
	private sealed class Prepared
	{
		public string BodyName;

		public GameObject Model;

		public ModelSkinController Controller;

		public SkinDef Skin;

		public Mesh Mesh;

		public Mesh Reference;

		public Material Material;
	}

	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 sealed class MineSurveyorVisuals : MonoBehaviour
	{
		private sealed class Saved
		{
			public Renderer Renderer;

			public Mesh Mesh;

			public Material[] Materials;

			public Bounds Bounds;

			public bool Offscreen;

			public bool ChangeMesh;

			public bool ChangeMaterial;

			public Mesh AssignedMesh;

			public Material[] AssignedMaterials;

			public bool ChangeBounds;

			public Bounds AssignedBounds;

			public bool ChangeOffscreen;

			public bool AssignedOffscreen;
		}

		private readonly Dictionary<Renderer, Saved> changed = new Dictionary<Renderer, Saved>();

		private ModelSkinController controller;

		private CharacterBody body;

		private EntityStateMachine[] machines;

		private bool lobbyDirty = true;

		private static readonly FieldInfo Blueprint = typeof(PlaceTurret).GetField("blueprints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo Wrist = typeof(PlaceTurret).GetField("wristDisplayObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private void Applied(int index)
		{
			if (!OwnSkin() && changed.Count > 0)
			{
				Restore();
			}
			lobbyDirty = true;
		}

		private void Start()
		{
			controller = ((Component)this).GetComponentInChildren<ModelSkinController>(true);
			body = ((Component)this).GetComponentInParent<CharacterBody>();
			machines = (EntityStateMachine[])(Object.op_Implicit((Object)(object)body) ? ((Array)((Component)body).GetComponents<EntityStateMachine>()) : ((Array)new EntityStateMachine[0]));
			if (Object.op_Implicit((Object)(object)controller))
			{
				controller.onSkinApplied += Applied;
			}
		}

		private bool OwnSkin()
		{
			if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null)
			{
				return false;
			}
			int currentSkinIndex = controller.currentSkinIndex;
			if (currentSkinIndex >= 0 && currentSkinIndex < controller.skins.Length && Object.op_Implicit((Object)(object)controller.skins[currentSkinIndex]))
			{
				return ((Object)controller.skins[currentSkinIndex]).name.StartsWith("skinEclipsePlaytestEngineerE2_", StringComparison.Ordinal);
			}
			return false;
		}

		private Saved Save(Renderer r)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (changed.TryGetValue(r, out var value))
			{
				return value;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
			MeshFilter component = ((Component)r).GetComponent<MeshFilter>();
			value = new Saved
			{
				Renderer = r,
				Materials = r.sharedMaterials,
				Mesh = (Object.op_Implicit((Object)(object)val) ? val.sharedMesh : (Object.op_Implicit((Object)(object)component) ? component.sharedMesh : null)),
				Bounds = (Bounds)(Object.op_Implicit((Object)(object)val) ? ((Renderer)val).localBounds : default(Bounds)),
				Offscreen = (Object.op_Implicit((Object)(object)val) && val.updateWhenOffscreen)
			};
			changed.Add(r, value);
			return value;
		}

		private void ApplySkinned(SkinnedMeshRenderer r, string asset, bool keepMaterial)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_008b: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Saved saved = Save((Renderer)(object)r);
			saved.ChangeMesh = true;
			saved.ChangeMaterial = !keepMaterial;
			Mesh val = (saved.AssignedMesh = instance.MeshFor(asset, r));
			if ((Object)(object)r.sharedMesh != (Object)(object)val)
			{
				r.sharedMesh = val;
				Mesh val2 = new Mesh();
				r.BakeMesh(val2);
				Bounds bounds = saved.Bounds;
				Bounds bounds2 = val2.bounds;
				((Bounds)(ref bounds)).Encapsulate(((Bounds)(ref bounds2)).min);
				bounds2 = val2.bounds;
				((Bounds)(ref bounds)).Encapsulate(((Bounds)(ref bounds2)).max);
				((Bounds)(ref bounds)).Expand(((Bounds)(ref bounds)).size * 0.5f);
				((Renderer)r).localBounds = bounds;
				saved.ChangeBounds = true;
				saved.AssignedBounds = bounds;
				Object.Destroy((Object)(object)val2);
			}
			r.updateWhenOffscreen = true;
			saved.ChangeOffscreen = true;
			saved.AssignedOffscreen = true;
			if (!keepMaterial)
			{
				((Renderer)r).sharedMaterial = instance.prepared.Single((Prepared p) => p.BodyName == ((asset == "walker") ? "EngiWalkerTurretBody" : "EngiTurretBody")).Material;
				saved.AssignedMaterials = ((Renderer)r).sharedMaterials;
			}
		}

		private void Restore()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			foreach (Saved value in changed.Values)
			{
				if (!Object.op_Implicit((Object)(object)value.Renderer))
				{
					continue;
				}
				Renderer renderer = value.Renderer;
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				MeshFilter component = ((Component)value.Renderer).GetComponent<MeshFilter>();
				if (Object.op_Implicit((Object)(object)val))
				{
					if (value.ChangeMesh && (Object)(object)val.sharedMesh == (Object)(object)value.AssignedMesh)
					{
						if (value.ChangeBounds && ((Renderer)val).localBounds == value.AssignedBounds)
						{
							((Renderer)val).localBounds = value.Bounds;
						}
						if (value.ChangeOffscreen && val.updateWhenOffscreen == value.AssignedOffscreen)
						{
							val.updateWhenOffscreen = value.Offscreen;
						}
						val.sharedMesh = value.Mesh;
					}
				}
				else if (Object.op_Implicit((Object)(object)component) && value.ChangeMesh && (Object)(object)component.sharedMesh == (Object)(object)value.AssignedMesh)
				{
					component.sharedMesh = value.Mesh;
				}
				if (value.ChangeMaterial && value.AssignedMaterials != null && value.Renderer.sharedMaterials.SequenceEqual(value.AssignedMaterials))
				{
					value.Renderer.sharedMaterials = value.Materials;
				}
			}
			changed.Clear();
		}

		private void LateUpdate()
		{
			if (!Object.op_Implicit((Object)(object)instance) || !instance.registered)
			{
				return;
			}
			Renderer[] array = changed.Keys.Where((Renderer r) => !Object.op_Implicit((Object)(object)r)).ToArray();
			foreach (Renderer key in array)
			{
				changed.Remove(key);
			}
			if (!OwnSkin())
			{
				if (changed.Count > 0)
				{
					Restore();
				}
				lobbyDirty = true;
				return;
			}
			if (!Object.op_Implicit((Object)(object)body))
			{
				if (!lobbyDirty)
				{
					return;
				}
				lobbyDirty = false;
				SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
				foreach (SkinnedMeshRenderer val in componentsInChildren)
				{
					if (val.bones.Length == 15 && Object.op_Implicit((Object)(object)((Component)this).transform.Find("TurretHolder")) && ((Component)val).transform.IsChildOf(((Component)this).transform.Find("TurretHolder")))
					{
						ApplySkinned(val, "turret", keepMaterial: false);
					}
					else if (((Object)val).name.IndexOf("Mine", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						Saved saved = Save((Renderer)(object)val);
						saved.ChangeMaterial = true;
						((Renderer)val).sharedMaterials = instance.PaintMine(saved.Materials);
						saved.AssignedMaterials = ((Renderer)val).sharedMaterials;
					}
				}
				MeshRenderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val2 in componentsInChildren2)
				{
					if (((Object)val2).name == "EngiMineMesh")
					{
						Saved saved2 = Save((Renderer)(object)val2);
						saved2.ChangeMaterial = true;
						((Renderer)val2).sharedMaterials = instance.PaintMine(saved2.Materials);
						saved2.AssignedMaterials = ((Renderer)val2).sharedMaterials;
					}
				}
				return;
			}
			EntityStateMachine[] array2 = machines;
			for (int num = 0; num < array2.Length; num++)
			{
				EntityState state = array2[num].state;
				PlaceTurret val3 = (PlaceTurret)(object)((state is PlaceTurret) ? state : null);
				if (val3 == null)
				{
					continue;
				}
				string asset = ((val3 is PlaceWalkerTurret) ? "walker" : "turret");
				object? obj = Blueprint?.GetValue(val3);
				BlueprintController val4 = (BlueprintController)((obj is BlueprintController) ? obj : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					SkinnedMeshRenderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<SkinnedMeshRenderer>(true);
					foreach (SkinnedMeshRenderer val5 in componentsInChildren)
					{
						if (val5.bones.Length == 15)
						{
							ApplySkinned(val5, asset, keepMaterial: true);
						}
					}
				}
				object? obj2 = Wrist?.GetValue(val3);
				GameObject val6 = (GameObject)((obj2 is GameObject) ? obj2 : null);
				if (!Object.op_Implicit((Object)(object)val6))
				{
					continue;
				}
				MeshFilter[] componentsInChildren3 = val6.GetComponentsInChildren<MeshFilter>(true);
				foreach (MeshFilter val7 in componentsInChildren3)
				{
					if (((Object)val7).name == "EngiTurretMesh")
					{
						Renderer component = ((Component)val7).GetComponent<Renderer>();
						Saved saved3 = Save(component);
						saved3.ChangeMesh = true;
						val7.sharedMesh = instance.WristMesh(asset);
						saved3.AssignedMesh = val7.sharedMesh;
					}
				}
			}
		}

		private void OnDisable()
		{
			Restore();
			lobbyDirty = true;
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)controller))
			{
				controller.onSkinApplied -= Applied;
			}
		}
	}

	public const string Guid = "eclipseplaytest.engineer.e2";

	public const string Version = "0.1.2";

	private static EngineerMineSurveyor instance;

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

	private float registrationDeadline;

	private string folder;

	private SkinDef skin;

	private GameObject modelPrefab;

	private readonly List<Prepared> prepared = new List<Prepared>();

	private bool registered;

	private static readonly Design[] Designs = new Design[1]
	{
		new Design("mine-surveyor", "Mine Surveyor (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)214, (byte)160, (byte)48, byte.MaxValue),
			new Color32((byte)223, (byte)211, (byte)175, byte.MaxValue),
			new Color32((byte)91, (byte)93, (byte)82, byte.MaxValue),
			new Color32((byte)47, (byte)53, (byte)49, byte.MaxValue)
		})
	};

	private GameObject cosmeticStorage;

	private Texture2D minePaint;

	private readonly Dictionary<string, Mesh> remappedMeshes = new Dictionary<string, Mesh>();

	private readonly Dictionary<Material, Material> mineMaterials = new Dictionary<Material, Material>();

	private readonly Dictionary<string, Mesh> wristMeshes = new Dictionary<string, Mesh>();

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

	[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)("ENGINEER_E2_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ENGINEER_E2_REGISTRATION_BEGIN 0.1.2");
		string[][] array = new string[3][]
		{
			new string[4] { "EngiTurretBody", "turret", "15", "skinEngiTurretDefault" },
			new string[4] { "EngiWalkerTurretBody", "walker", "15", "skinEngiWalkerTurretDefault" },
			new string[4] { "EngiBody", "mine-surveyor", "83", "skinEngiDefault" }
		};
		foreach (string[] array2 in array)
		{
			IEnumerator routine = Prepare(array2[0], array2[1], int.Parse(array2[2]), array2[3]);
			while (routine.MoveNext())
			{
				yield return null;
			}
		}
		Prepared bodySkin = prepared.Single((Prepared p) => p.BodyName == "EngiBody");
		bodySkin.Skin.skinDefParams.minionSkinReplacements = (MinionSkinReplacement[])(object)new MinionSkinReplacement[2]
		{
			new MinionSkinReplacement
			{
				minionBodyPrefab = BodyCatalog.FindBodyPrefab("EngiTurretBody"),
				minionSkin = prepared.Single((Prepared p) => p.BodyName == "EngiTurretBody").Skin
			},
			new MinionSkinReplacement
			{
				minionBodyPrefab = BodyCatalog.FindBodyPrefab("EngiWalkerTurretBody"),
				minionSkin = prepared.Single((Prepared p) => p.BodyName == "EngiWalkerTurretBody").Skin
			}
		};
		IEnumerator ghostRoutine = PrepareMineGhosts(bodySkin.Skin);
		while (ghostRoutine.MoveNext())
		{
			yield return null;
		}
		foreach (Prepared item in prepared)
		{
			item.Controller.skins = item.Controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { item.Skin }).ToArray();
		}
		modelPrefab = bodySkin.Model;
		skin = bodySkin.Skin;
		registered = true;
		foreach (Prepared item2 in prepared)
		{
			if (!Object.op_Implicit((Object)(object)item2.Model.GetComponent<MineSurveyorVisuals>()))
			{
				item2.Model.AddComponent<MineSurveyorVisuals>();
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ENGINEER_E2_REGISTERED Mine Surveyor, both turret variants, unlocked=true version=0.1.2");
	}

	private IEnumerator Prepare(string bodyName, string assetName, int boneCount, string defaultName)
	{
		GameObject val = BodyCatalog.FindBodyPrefab(bodyName);
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("Missing body " + bodyName);
		}
		GameObject model = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = model.GetComponent<ModelSkinController>();
		SkinDef baseSkin = null;
		if (Object.op_Implicit((Object)(object)controller) && controller.skins != null && controller.skins.Length != 0)
		{
			baseSkin = controller.skins[0];
		}
		if (!Object.op_Implicit((Object)(object)baseSkin))
		{
			AsyncOperationHandle<SkinDef> h = Addressables.LoadAssetAsync<SkinDef>((object)("RoR2/Base/Engi/" + defaultName + ".asset"));
			retainedAssets.Add(AsyncOperationHandle<SkinDef>.op_Implicit(h));
			while (!h.IsDone)
			{
				CheckLoadDeadline("default skin " + bodyName);
				yield return null;
			}
			baseSkin = h.Result;
		}
		if (!Object.op_Implicit((Object)(object)baseSkin))
		{
			throw new InvalidOperationException("Missing default skin " + bodyName);
		}
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> h2 = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(h2));
			while (!h2.IsDone)
			{
				CheckLoadDeadline("parameters " + bodyName);
				yield return null;
			}
			bp = h2.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Missing parameters " + bodyName);
		}
		SkinnedMeshRenderer target = model.GetComponentsInChildren<SkinnedMeshRenderer>(true).Single((SkinnedMeshRenderer r) => r.bones.Length == boneCount);
		Mesh reference = target.sharedMesh;
		if (!Object.op_Implicit((Object)(object)reference))
		{
			MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
			reference = val2.mesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				AsyncOperationHandle<Mesh> h3 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(h3));
				while (!h3.IsDone)
				{
					CheckLoadDeadline("mesh " + bodyName);
					yield return null;
				}
				reference = h3.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != target.bones.Length)
		{
			throw new InvalidOperationException("Bind pose mismatch " + bodyName);
		}
		RendererInfo ri = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material val3 = ri.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)val3) && ri.defaultMaterialAddress != null && ((AssetReference)ri.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> h4 = Addressables.LoadAssetAsync<Material>(((AssetReference)ri.defaultMaterialAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(h4));
			while (!h4.IsDone)
			{
				CheckLoadDeadline("material " + bodyName);
				yield return null;
			}
			val3 = h4.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("Missing native material " + bodyName);
		}
		Mesh val4 = ReadMesh(Path.Combine(folder, assetName + ".meshbin"), target, reference);
		((Object)val4).name = "EclipsePlaytest_EngineerE2_" + assetName;
		Material val5 = new Material(val3)
		{
			name = "matEclipsePlaytest_EngineerE2_" + assetName
		};
		val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
		val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
		val5.SetColor("_Color", Color.white);
		val5.SetFloat("_NormalStrength", 0.3f);
		val5.SetFloat("_Smoothness", 0.28f);
		val5.SetFloat("_SpecularStrength", 0.35f);
		val5.SetFloat("_SpecularExponent", 8f);
		val5.SetFloat("_EmPower", 0f);
		val5.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		val5.DisableKeyword("LIMBREMOVAL");
		val5.SetFloat("_LimbRemovalOn", 0f);
		ri.defaultMaterial = val5;
		ri.defaultMaterialAddress = new AssetReferenceT<Material>("");
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		val6.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { ri };
		val6.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
		{
			new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			}
		};
		SkinDef val7 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val7).name = "skinEclipsePlaytestEngineerE2_" + assetName;
		val7.nameToken = "ECLIPSEPLAYTEST_ENGINEER_E2_" + assetName.ToUpperInvariant().Replace('-', '_');
		LanguageAPI.Add(val7.nameToken, (bodyName == "EngiBody") ? "Mine Surveyor (Playtest)" : ("Mine Surveyor " + assetName));
		val7.icon = CreateIcon(Designs[0].Colors);
		val7.unlockableDef = null;
		val7.rootObject = model;
		val7.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val7.skinDefParams = val6;
		if (!Object.op_Implicit((Object)(object)controller))
		{
			controller = model.AddComponent<ModelSkinController>();
			controller.skins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		}
		prepared.Add(new Prepared
		{
			BodyName = bodyName,
			Model = model,
			Controller = controller,
			Skin = val7,
			Mesh = val4,
			Reference = reference,
			Material = val5
		});
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ENGINEER_E2_PREPARED body=" + bodyName + " vertices=" + val4.vertexCount + " unlocked=true"));
	}

	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 == "EngiBody"));
		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))
		{
			ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
			val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			if (!Object.op_Implicit((Object)(object)val.displayPrefab.GetComponent<MineSurveyorVisuals>()))
			{
				val.displayPrefab.AddComponent<MineSurveyorVisuals>();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ENGINEER_E2_DISPLAY_READY skins=" + val2.skins.Length));
		}
	}

	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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: 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_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: 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_01b6: 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_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_0405: 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_0422: 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_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_043a: 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_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_0458: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Expected O, but got Unknown
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: 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_038c: 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)) != "PWE2")
		{
			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 != renderer.bones.Length)
		{
			throw new InvalidDataException("Invalid mesh dimensions.");
		}
		int[] array = new int[num3];
		HashSet<int> hashSet = new HashSet<int>();
		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 || !hashSet.Add(array[i]))
			{
				throw new InvalidDataException("Missing/duplicate reference bone: " + name);
			}
		}
		Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[num3];
		for (int num5 = 0; num5 < num3; num5++)
		{
			Matrix4x4 val = default(Matrix4x4);
			for (int num6 = 0; num6 < 4; num6++)
			{
				for (int num7 = 0; num7 < 4; num7++)
				{
					float num8 = binaryReader.ReadSingle();
					if (float.IsNaN(num8) || float.IsInfinity(num8))
					{
						throw new InvalidDataException("Invalid bind matrix.");
					}
					((Matrix4x4)(ref val))[num6, num7] = num8;
				}
			}
			if (Math.Abs(((Matrix4x4)(ref val)).determinant) < 1E-05f)
			{
				throw new InvalidDataException("Singular bind matrix.");
			}
			array2[array[num5]] = val;
		}
		Vector3[] array3 = (Vector3[])(object)new Vector3[num];
		Vector3[] array4 = (Vector3[])(object)new Vector3[num];
		Vector2[] array5 = (Vector2[])(object)new Vector2[num];
		BoneWeight[] array6 = (BoneWeight[])(object)new BoneWeight[num];
		for (int num9 = 0; num9 < num; num9++)
		{
			array3[num9] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array4[num9] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array5[num9] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			int[] array7 = new int[4];
			for (int num10 = 0; num10 < 4; num10++)
			{
				int num11 = binaryReader.ReadInt32();
				if (num11 < 0 || num11 >= num3)
				{
					throw new InvalidDataException("Bone out of range.");
				}
				array7[num10] = array[num11];
			}
			float[] array8 = new float[4];
			for (int num12 = 0; num12 < 4; num12++)
			{
				array8[num12] = binaryReader.ReadSingle();
			}
			if (array8.Any((float n) => float.IsNaN(n) || float.IsInfinity(n) || n < 0f) || Math.Abs(array8.Sum() - 1f) > 0.002f)
			{
				throw new InvalidDataException("Invalid skin weight.");
			}
			if (!Finite(array3[num9]) || !Finite(array4[num9]))
			{
				throw new InvalidDataException("Non-finite vertex.");
			}
			int num13 = num9;
			BoneWeight val2 = default(BoneWeight);
			((BoneWeight)(ref val2)).boneIndex0 = array7[0];
			((BoneWeight)(ref val2)).boneIndex1 = array7[1];
			((BoneWeight)(ref val2)).boneIndex2 = array7[2];
			((BoneWeight)(ref val2)).boneIndex3 = array7[3];
			((BoneWeight)(ref val2)).weight0 = array8[0];
			((BoneWeight)(ref val2)).weight1 = array8[1];
			((BoneWeight)(ref val2)).weight2 = array8[2];
			((BoneWeight)(ref val2)).weight3 = array8[3];
			array6[num13] = val2;
		}
		int[] array9 = new int[num2];
		for (int num14 = 0; num14 < num2; num14++)
		{
			array9[num14] = binaryReader.ReadInt32();
			if (array9[num14] < 0 || array9[num14] >= num)
			{
				throw new InvalidDataException("Triangle out of range.");
			}
		}
		if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
		{
			throw new InvalidDataException("Unexpected trailing mesh data.");
		}
		Mesh val3 = new Mesh
		{
			name = "EclipsePlaytestEngineerMineSurveyor",
			indexFormat = (IndexFormat)(num > 65535),
			vertices = array3,
			normals = array4,
			uv = array5,
			boneWeights = array6,
			bindposes = array2,
			triangles = array9
		};
		val3.RecalculateBounds();
		val3.RecalculateTangents();
		return val3;
	}

	private IEnumerator PrepareMineGhosts(SkinDef bodySkin)
	{
		cosmeticStorage = new GameObject("MineSurveyorCosmeticPrefabs");
		cosmeticStorage.SetActive(false);
		Object.DontDestroyOnLoad((Object)(object)cosmeticStorage);
		minePaint = new Texture2D(2, 2, (TextureFormat)4, false);
		minePaint.SetPixels(Enumerable.Repeat<Color>(new Color(0.65f, 0.39f, 0.07f, 0.2f), 4).ToArray());
		minePaint.Apply();
		List<ProjectileGhostReplacement> replacements = new List<ProjectileGhostReplacement>();
		string[] array = new string[2] { "EngiMine", "SpiderMine" };
		foreach (string name in array)
		{
			AsyncOperationHandle<GameObject> h = Addressables.LoadAssetAsync<GameObject>((object)("RoR2/Base/Engi/" + name + ".prefab"));
			retainedAssets.Add(AsyncOperationHandle<GameObject>.op_Implicit(h));
			while (!h.IsDone)
			{
				CheckLoadDeadline(name);
				yield return null;
			}
			if (!Object.op_Implicit((Object)(object)h.Result))
			{
				throw new InvalidOperationException("Missing mine projectile " + name);
			}
			ProjectileController component = h.Result.GetComponent<ProjectileController>();
			GameObject val = component.ghostPrefab;
			if (!Object.op_Implicit((Object)(object)val) && component.ghostPrefabAddress != null && ((AssetReference)component.ghostPrefabAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<GameObject> gh = Addressables.LoadAssetAsync<GameObject>(((AssetReference)component.ghostPrefabAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<GameObject>.op_Implicit(gh));
				while (!gh.IsDone)
				{
					CheckLoadDeadline(name + " ghost");
					yield return null;
				}
				val = gh.Result;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Missing mine ghost " + name);
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, cosmeticStorage.transform);
			((Object)val2).name = "EclipseMineSurveyor_" + name + "Ghost";
			val2.SetActive(true);
			SkinnedMeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren)
			{
				((Renderer)val3).sharedMaterials = PaintMine(((Renderer)val3).sharedMaterials);
			}
			replacements.Add(new ProjectileGhostReplacement
			{
				projectilePrefab = h.Result,
				projectileGhostReplacementPrefab = val2,
				ghostReplacementAddress = new AssetReferenceT<GameObject>("")
			});
		}
		bodySkin.skinDefParams.projectileGhostReplacements = replacements.ToArray();
	}

	private Material[] PaintMine(Material[] sources)
	{
		return ((IEnumerable<Material>)sources).Select((Func<Material, Material>)delegate(Material src)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)src))
			{
				return src;
			}
			if (mineMaterials.TryGetValue(src, out var value))
			{
				return value;
			}
			value = new Material(src)
			{
				name = "MineSurveyorMine_" + ((Object)src).name
			};
			value.SetTexture("_MainTex", (Texture)(object)minePaint);
			value.SetColor("_Color", Color.white);
			value.SetFloat("_Smoothness", 0.25f);
			value.SetFloat("_SpecularStrength", 0.3f);
			mineMaterials.Add(src, value);
			return value;
		}).ToArray();
	}

	private Mesh MeshFor(string asset, SkinnedMeshRenderer target)
	{
		string key = asset + "|" + string.Join("|", target.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "<null>" : ((Object)b).name));
		if (!remappedMeshes.TryGetValue(key, out var value))
		{
			value = ReadMesh(Path.Combine(folder, asset + ".meshbin"), target, target.sharedMesh);
			remappedMeshes.Add(key, value);
		}
		return value;
	}

	private Mesh WristMesh(string asset)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_00b8: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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)
		if (wristMeshes.TryGetValue(asset, out var value))
		{
			return value;
		}
		Prepared prepared = this.prepared.Single((Prepared p) => p.BodyName == ((asset == "walker") ? "EngiWalkerTurretBody" : "EngiTurretBody"));
		prepared.Model.GetComponentsInChildren<SkinnedMeshRenderer>(true).Single((SkinnedMeshRenderer x) => x.bones.Length == 15);
		Matrix4x4 val = ((Matrix4x4)(ref prepared.Reference.bindposes[0])).inverse * prepared.Mesh.bindposes[0];
		value = Object.Instantiate<Mesh>(prepared.Mesh);
		Vector3[] vertices = value.vertices;
		Vector3[] normals = value.normals;
		Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
		Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
		for (int num = 0; num < vertices.Length; num++)
		{
			vertices[num] = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[num]);
			int num2 = num;
			Vector3 val2 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[num]);
			normals[num2] = ((Vector3)(ref val2)).normalized;
		}
		value.vertices = vertices;
		value.normals = normals;
		value.RecalculateBounds();
		value.RecalculateTangents();
		wristMeshes.Add(asset, value);
		return value;
	}

	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;
	}
}

BepInEx/plugins/Local-Eclipse_Engineer_Skins_Playtest/Local-Engineer_Union_Builder_Playtest/EngineerUnionBuilder.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using EntityStates;
using EntityStates.Engi.EngiWeapon;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.Projectile;
using RoR2.UI.MainMenu;
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 EngineerUnionBuilderPlaytest;

[BepInPlugin("eclipseplaytest.engineer.e1", "Engineer - Union Builder (Playtest)", "0.1.5")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class EngineerUnionBuilder : BaseUnityPlugin
{
	private sealed class Prepared
	{
		public string BodyName;

		public GameObject Model;

		public ModelSkinController Controller;

		public SkinDef Skin;

		public Mesh Mesh;

		public Mesh Reference;

		public Material Material;
	}

	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 sealed class UnionVisuals : MonoBehaviour
	{
		private sealed class Saved
		{
			public Renderer Renderer;

			public Mesh Mesh;

			public Material[] Materials;

			public Bounds Bounds;

			public bool Offscreen;

			public bool ChangeMesh;

			public bool ChangeMaterial;

			public Mesh AssignedMesh;

			public Material[] AssignedMaterials;

			public bool ChangeBounds;

			public Bounds AssignedBounds;

			public bool ChangeOffscreen;

			public bool AssignedOffscreen;
		}

		private readonly Dictionary<Renderer, Saved> changed = new Dictionary<Renderer, Saved>();

		private ModelSkinController controller;

		private CharacterBody body;

		private EntityStateMachine[] machines;

		private bool lobbyDirty = true;

		private static readonly FieldInfo Blueprint = typeof(PlaceTurret).GetField("blueprints", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo Wrist = typeof(PlaceTurret).GetField("wristDisplayObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private void Applied(int index)
		{
			if (!OwnSkin() && changed.Count > 0)
			{
				Restore();
			}
			lobbyDirty = true;
		}

		private void Start()
		{
			controller = ((Component)this).GetComponentInChildren<ModelSkinController>(true);
			body = ((Component)this).GetComponentInParent<CharacterBody>();
			machines = (EntityStateMachine[])(Object.op_Implicit((Object)(object)body) ? ((Array)((Component)body).GetComponents<EntityStateMachine>()) : ((Array)new EntityStateMachine[0]));
			if (Object.op_Implicit((Object)(object)controller))
			{
				controller.onSkinApplied += Applied;
			}
		}

		private bool OwnSkin()
		{
			if (!Object.op_Implicit((Object)(object)controller) || controller.skins == null)
			{
				return false;
			}
			int currentSkinIndex = controller.currentSkinIndex;
			if (currentSkinIndex >= 0 && currentSkinIndex < controller.skins.Length && Object.op_Implicit((Object)(object)controller.skins[currentSkinIndex]))
			{
				return ((Object)controller.skins[currentSkinIndex]).name.StartsWith("skinEclipsePlaytestEngineerE1_", StringComparison.Ordinal);
			}
			return false;
		}

		private Saved Save(Renderer r)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			if (changed.TryGetValue(r, out var value))
			{
				return value;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((r is SkinnedMeshRenderer) ? r : null);
			MeshFilter component = ((Component)r).GetComponent<MeshFilter>();
			value = new Saved
			{
				Renderer = r,
				Materials = r.sharedMaterials,
				Mesh = (Object.op_Implicit((Object)(object)val) ? val.sharedMesh : (Object.op_Implicit((Object)(object)component) ? component.sharedMesh : null)),
				Bounds = (Bounds)(Object.op_Implicit((Object)(object)val) ? ((Renderer)val).localBounds : default(Bounds)),
				Offscreen = (Object.op_Implicit((Object)(object)val) && val.updateWhenOffscreen)
			};
			changed.Add(r, value);
			return value;
		}

		private void ApplySkinned(SkinnedMeshRenderer r, string asset, bool keepMaterial)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_008b: 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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			Saved saved = Save((Renderer)(object)r);
			saved.ChangeMesh = true;
			saved.ChangeMaterial = !keepMaterial;
			Mesh val = (saved.AssignedMesh = instance.MeshFor(asset, r));
			if ((Object)(object)r.sharedMesh != (Object)(object)val)
			{
				r.sharedMesh = val;
				Mesh val2 = new Mesh();
				r.BakeMesh(val2);
				Bounds bounds = saved.Bounds;
				Bounds bounds2 = val2.bounds;
				((Bounds)(ref bounds)).Encapsulate(((Bounds)(ref bounds2)).min);
				bounds2 = val2.bounds;
				((Bounds)(ref bounds)).Encapsulate(((Bounds)(ref bounds2)).max);
				((Bounds)(ref bounds)).Expand(((Bounds)(ref bounds)).size * 0.5f);
				((Renderer)r).localBounds = bounds;
				saved.ChangeBounds = true;
				saved.AssignedBounds = bounds;
				Object.Destroy((Object)(object)val2);
			}
			r.updateWhenOffscreen = true;
			saved.ChangeOffscreen = true;
			saved.AssignedOffscreen = true;
			if (!keepMaterial)
			{
				((Renderer)r).sharedMaterial = instance.prepared.Single((Prepared p) => p.BodyName == ((asset == "walker") ? "EngiWalkerTurretBody" : "EngiTurretBody")).Material;
				saved.AssignedMaterials = ((Renderer)r).sharedMaterials;
			}
		}

		private void Restore()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			foreach (Saved value in changed.Values)
			{
				if (!Object.op_Implicit((Object)(object)value.Renderer))
				{
					continue;
				}
				Renderer renderer = value.Renderer;
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
				MeshFilter component = ((Component)value.Renderer).GetComponent<MeshFilter>();
				if (Object.op_Implicit((Object)(object)val))
				{
					if (value.ChangeMesh && (Object)(object)val.sharedMesh == (Object)(object)value.AssignedMesh)
					{
						if (value.ChangeBounds && ((Renderer)val).localBounds == value.AssignedBounds)
						{
							((Renderer)val).localBounds = value.Bounds;
						}
						if (value.ChangeOffscreen && val.updateWhenOffscreen == value.AssignedOffscreen)
						{
							val.updateWhenOffscreen = value.Offscreen;
						}
						val.sharedMesh = value.Mesh;
					}
				}
				else if (Object.op_Implicit((Object)(object)component) && value.ChangeMesh && (Object)(object)component.sharedMesh == (Object)(object)value.AssignedMesh)
				{
					component.sharedMesh = value.Mesh;
				}
				if (value.ChangeMaterial && value.AssignedMaterials != null && value.Renderer.sharedMaterials.SequenceEqual(value.AssignedMaterials))
				{
					value.Renderer.sharedMaterials = value.Materials;
				}
			}
			changed.Clear();
		}

		private void LateUpdate()
		{
			if (!Object.op_Implicit((Object)(object)instance) || !instance.registered)
			{
				return;
			}
			Renderer[] array = changed.Keys.Where((Renderer r) => !Object.op_Implicit((Object)(object)r)).ToArray();
			foreach (Renderer key in array)
			{
				changed.Remove(key);
			}
			if (!OwnSkin())
			{
				if (changed.Count > 0)
				{
					Restore();
				}
				lobbyDirty = true;
				return;
			}
			if (!Object.op_Implicit((Object)(object)body))
			{
				if (!lobbyDirty)
				{
					return;
				}
				lobbyDirty = false;
				SkinnedMeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<SkinnedMeshRenderer>(true);
				foreach (SkinnedMeshRenderer val in componentsInChildren)
				{
					if (val.bones.Length == 15 && Object.op_Implicit((Object)(object)((Component)this).transform.Find("TurretHolder")) && ((Component)val).transform.IsChildOf(((Component)this).transform.Find("TurretHolder")))
					{
						ApplySkinned(val, "turret", keepMaterial: false);
					}
					else if (((Object)val).name.IndexOf("Mine", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						Saved saved = Save((Renderer)(object)val);
						saved.ChangeMaterial = true;
						((Renderer)val).sharedMaterials = instance.PaintMine(saved.Materials);
						saved.AssignedMaterials = ((Renderer)val).sharedMaterials;
					}
				}
				MeshRenderer[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer val2 in componentsInChildren2)
				{
					if (((Object)val2).name == "EngiMineMesh")
					{
						Saved saved2 = Save((Renderer)(object)val2);
						saved2.ChangeMaterial = true;
						((Renderer)val2).sharedMaterials = instance.PaintMine(saved2.Materials);
						saved2.AssignedMaterials = ((Renderer)val2).sharedMaterials;
					}
				}
				return;
			}
			EntityStateMachine[] array2 = machines;
			for (int num = 0; num < array2.Length; num++)
			{
				EntityState state = array2[num].state;
				PlaceTurret val3 = (PlaceTurret)(object)((state is PlaceTurret) ? state : null);
				if (val3 == null)
				{
					continue;
				}
				string asset = ((val3 is PlaceWalkerTurret) ? "walker" : "turret");
				object? obj = Blueprint?.GetValue(val3);
				BlueprintController val4 = (BlueprintController)((obj is BlueprintController) ? obj : null);
				if (Object.op_Implicit((Object)(object)val4))
				{
					SkinnedMeshRenderer[] componentsInChildren = ((Component)val4).GetComponentsInChildren<SkinnedMeshRenderer>(true);
					foreach (SkinnedMeshRenderer val5 in componentsInChildren)
					{
						if (val5.bones.Length == 15)
						{
							ApplySkinned(val5, asset, keepMaterial: true);
						}
					}
				}
				object? obj2 = Wrist?.GetValue(val3);
				GameObject val6 = (GameObject)((obj2 is GameObject) ? obj2 : null);
				if (!Object.op_Implicit((Object)(object)val6))
				{
					continue;
				}
				MeshFilter[] componentsInChildren3 = val6.GetComponentsInChildren<MeshFilter>(true);
				foreach (MeshFilter val7 in componentsInChildren3)
				{
					if (((Object)val7).name == "EngiTurretMesh")
					{
						Renderer component = ((Component)val7).GetComponent<Renderer>();
						Saved saved3 = Save(component);
						saved3.ChangeMesh = true;
						val7.sharedMesh = instance.WristMesh(asset);
						saved3.AssignedMesh = val7.sharedMesh;
					}
				}
			}
		}

		private void OnDisable()
		{
			Restore();
			lobbyDirty = true;
		}

		private void OnDestroy()
		{
			if (Object.op_Implicit((Object)(object)controller))
			{
				controller.onSkinApplied -= Applied;
			}
		}
	}

	public const string Guid = "eclipseplaytest.engineer.e1";

	public const string Version = "0.1.5";

	private static EngineerUnionBuilder instance;

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

	private float registrationDeadline;

	private string folder;

	private SkinDef skin;

	private GameObject modelPrefab;

	private readonly List<Prepared> prepared = new List<Prepared>();

	private bool registered;

	private static readonly Design[] Designs = new Design[1]
	{
		new Design("union-builder", "Union Builder (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)248, (byte)199, (byte)38, byte.MaxValue),
			new Color32((byte)177, (byte)67, (byte)49, byte.MaxValue),
			new Color32((byte)95, (byte)73, (byte)48, byte.MaxValue),
			new Color32((byte)52, (byte)62, (byte)62, byte.MaxValue)
		})
	};

	private GameObject cosmeticStorage;

	private Texture2D minePaint;

	private readonly Dictionary<string, Mesh> remappedMeshes = new Dictionary<string, Mesh>();

	private readonly Dictionary<Material, Material> mineMaterials = new Dictionary<Material, Material>();

	private readonly Dictionary<string, Mesh> wristMeshes = new Dictionary<string, Mesh>();

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

	[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)("ENGINEER_E1_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ENGINEER_E1_REGISTRATION_BEGIN 0.1.5");
		string[][] array = new string[3][]
		{
			new string[4] { "EngiTurretBody", "turret", "15", "skinEngiTurretDefault" },
			new string[4] { "EngiWalkerTurretBody", "walker", "15", "skinEngiWalkerTurretDefault" },
			new string[4] { "EngiBody", "union-builder", "83", "skinEngiDefault" }
		};
		foreach (string[] array2 in array)
		{
			IEnumerator routine = Prepare(array2[0], array2[1], int.Parse(array2[2]), array2[3]);
			while (routine.MoveNext())
			{
				yield return null;
			}
		}
		Prepared bodySkin = prepared.Single((Prepared p) => p.BodyName == "EngiBody");
		bodySkin.Skin.skinDefParams.minionSkinReplacements = (MinionSkinReplacement[])(object)new MinionSkinReplacement[2]
		{
			new MinionSkinReplacement
			{
				minionBodyPrefab = BodyCatalog.FindBodyPrefab("EngiTurretBody"),
				minionSkin = prepared.Single((Prepared p) => p.BodyName == "EngiTurretBody").Skin
			},
			new MinionSkinReplacement
			{
				minionBodyPrefab = BodyCatalog.FindBodyPrefab("EngiWalkerTurretBody"),
				minionSkin = prepared.Single((Prepared p) => p.BodyName == "EngiWalkerTurretBody").Skin
			}
		};
		IEnumerator ghostRoutine = PrepareMineGhosts(bodySkin.Skin);
		while (ghostRoutine.MoveNext())
		{
			yield return null;
		}
		foreach (Prepared item in prepared)
		{
			item.Controller.skins = item.Controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { item.Skin }).ToArray();
		}
		modelPrefab = bodySkin.Model;
		skin = bodySkin.Skin;
		registered = true;
		foreach (Prepared item2 in prepared)
		{
			if (!Object.op_Implicit((Object)(object)item2.Model.GetComponent<UnionVisuals>()))
			{
				item2.Model.AddComponent<UnionVisuals>();
			}
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ENGINEER_E1_REGISTERED Union Builder, both turret variants, unlocked=true version=0.1.5");
	}

	private IEnumerator Prepare(string bodyName, string assetName, int boneCount, string defaultName)
	{
		GameObject val = BodyCatalog.FindBodyPrefab(bodyName);
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("Missing body " + bodyName);
		}
		GameObject model = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = model.GetComponent<ModelSkinController>();
		SkinDef baseSkin = null;
		if (Object.op_Implicit((Object)(object)controller) && controller.skins != null && controller.skins.Length != 0)
		{
			baseSkin = controller.skins[0];
		}
		if (!Object.op_Implicit((Object)(object)baseSkin))
		{
			AsyncOperationHandle<SkinDef> h = Addressables.LoadAssetAsync<SkinDef>((object)("RoR2/Base/Engi/" + defaultName + ".asset"));
			retainedAssets.Add(AsyncOperationHandle<SkinDef>.op_Implicit(h));
			while (!h.IsDone)
			{
				CheckLoadDeadline("default skin " + bodyName);
				yield return null;
			}
			baseSkin = h.Result;
		}
		if (!Object.op_Implicit((Object)(object)baseSkin))
		{
			throw new InvalidOperationException("Missing default skin " + bodyName);
		}
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> h2 = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(h2));
			while (!h2.IsDone)
			{
				CheckLoadDeadline("parameters " + bodyName);
				yield return null;
			}
			bp = h2.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Missing parameters " + bodyName);
		}
		SkinnedMeshRenderer target = model.GetComponentsInChildren<SkinnedMeshRenderer>(true).Single((SkinnedMeshRenderer r) => r.bones.Length == boneCount);
		Mesh reference = target.sharedMesh;
		if (!Object.op_Implicit((Object)(object)reference))
		{
			MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
			reference = val2.mesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				AsyncOperationHandle<Mesh> h3 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(h3));
				while (!h3.IsDone)
				{
					CheckLoadDeadline("mesh " + bodyName);
					yield return null;
				}
				reference = h3.Result;
			}
		}
		if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != target.bones.Length)
		{
			throw new InvalidOperationException("Bind pose mismatch " + bodyName);
		}
		RendererInfo ri = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
		Material val3 = ri.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)val3) && ri.defaultMaterialAddress != null && ((AssetReference)ri.defaultMaterialAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<Material> h4 = Addressables.LoadAssetAsync<Material>(((AssetReference)ri.defaultMaterialAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(h4));
			while (!h4.IsDone)
			{
				CheckLoadDeadline("material " + bodyName);
				yield return null;
			}
			val3 = h4.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("Missing native material " + bodyName);
		}
		Mesh val4 = ReadMesh(Path.Combine(folder, assetName + ".meshbin"), target, reference);
		((Object)val4).name = "EclipsePlaytest_EngineerE1_" + assetName;
		Material val5 = new Material(val3)
		{
			name = "matEclipsePlaytest_EngineerE1_" + assetName
		};
		val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
		val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
		val5.SetColor("_Color", Color.white);
		val5.SetFloat("_NormalStrength", 0.3f);
		val5.SetFloat("_Smoothness", 0.28f);
		val5.SetFloat("_SpecularStrength", 0.35f);
		val5.SetFloat("_SpecularExponent", 8f);
		val5.SetFloat("_EmPower", 0f);
		val5.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
		val5.DisableKeyword("LIMBREMOVAL");
		val5.SetFloat("_LimbRemovalOn", 0f);
		ri.defaultMaterial = val5;
		ri.defaultMaterialAddress = new AssetReferenceT<Material>("");
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		val6.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { ri };
		val6.meshReplacements = (MeshReplacement[])(object)new MeshReplacement[1]
		{
			new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			}
		};
		SkinDef val7 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val7).name = "skinEclipsePlaytestEngineerE1_" + assetName;
		val7.nameToken = "ECLIPSEPLAYTEST_ENGINEER_E1_" + assetName.ToUpperInvariant().Replace('-', '_');
		LanguageAPI.Add(val7.nameToken, (bodyName == "EngiBody") ? "Union Builder (Playtest)" : ("Union Builder " + assetName));
		val7.icon = CreateIcon(Designs[0].Colors);
		val7.unlockableDef = null;
		val7.rootObject = model;
		val7.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val7.skinDefParams = val6;
		if (!Object.op_Implicit((Object)(object)controller))
		{
			controller = model.AddComponent<ModelSkinController>();
			controller.skins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		}
		prepared.Add(new Prepared
		{
			BodyName = bodyName,
			Model = model,
			Controller = controller,
			Skin = val7,
			Mesh = val4,
			Reference = reference,
			Material = val5
		});
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ENGINEER_E1_PREPARED body=" + bodyName + " vertices=" + val4.vertexCount + " unlocked=true"));
	}

	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 == "EngiBody"));
		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))
		{
			ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
			val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			if (!Object.op_Implicit((Object)(object)val.displayPrefab.GetComponent<UnionVisuals>()))
			{
				val.displayPrefab.AddComponent<UnionVisuals>();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ENGINEER_E1_DISPLAY_READY skins=" + val2.skins.Length));
		}
	}

	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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0209: 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_0229: Unknown result type (might be due to invalid IL or missing references)
		//IL_022e: 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_01b6: 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_0400: Unknown result type (might be due to invalid IL or missing references)
		//IL_0405: 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_0422: 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_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_043a: 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_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0452: Unknown result type (might be due to invalid IL or missing references)
		//IL_0458: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Expected O, but got Unknown
		//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_030f: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: 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_038c: 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)) != "PWE2")
		{
			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 != renderer.bones.Length)
		{
			throw new InvalidDataException("Invalid mesh dimensions.");
		}
		int[] array = new int[num3];
		HashSet<int> hashSet = new HashSet<int>();
		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 || !hashSet.Add(array[i]))
			{
				throw new InvalidDataException("Missing/duplicate reference bone: " + name);
			}
		}
		Matrix4x4[] array2 = (Matrix4x4[])(object)new Matrix4x4[num3];
		for (int num5 = 0; num5 < num3; num5++)
		{
			Matrix4x4 val = default(Matrix4x4);
			for (int num6 = 0; num6 < 4; num6++)
			{
				for (int num7 = 0; num7 < 4; num7++)
				{
					float num8 = binaryReader.ReadSingle();
					if (float.IsNaN(num8) || float.IsInfinity(num8))
					{
						throw new InvalidDataException("Invalid bind matrix.");
					}
					((Matrix4x4)(ref val))[num6, num7] = num8;
				}
			}
			if (Math.Abs(((Matrix4x4)(ref val)).determinant) < 1E-05f)
			{
				throw new InvalidDataException("Singular bind matrix.");
			}
			array2[array[num5]] = val;
		}
		Vector3[] array3 = (Vector3[])(object)new Vector3[num];
		Vector3[] array4 = (Vector3[])(object)new Vector3[num];
		Vector2[] array5 = (Vector2[])(object)new Vector2[num];
		BoneWeight[] array6 = (BoneWeight[])(object)new BoneWeight[num];
		for (int num9 = 0; num9 < num; num9++)
		{
			array3[num9] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array4[num9] = new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
			array5[num9] = new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
			int[] array7 = new int[4];
			for (int num10 = 0; num10 < 4; num10++)
			{
				int num11 = binaryReader.ReadInt32();
				if (num11 < 0 || num11 >= num3)
				{
					throw new InvalidDataException("Bone out of range.");
				}
				array7[num10] = array[num11];
			}
			float[] array8 = new float[4];
			for (int num12 = 0; num12 < 4; num12++)
			{
				array8[num12] = binaryReader.ReadSingle();
			}
			if (array8.Any((float n) => float.IsNaN(n) || float.IsInfinity(n) || n < 0f) || Math.Abs(array8.Sum() - 1f) > 0.002f)
			{
				throw new InvalidDataException("Invalid skin weight.");
			}
			if (!Finite(array3[num9]) || !Finite(array4[num9]))
			{
				throw new InvalidDataException("Non-finite vertex.");
			}
			int num13 = num9;
			BoneWeight val2 = default(BoneWeight);
			((BoneWeight)(ref val2)).boneIndex0 = array7[0];
			((BoneWeight)(ref val2)).boneIndex1 = array7[1];
			((BoneWeight)(ref val2)).boneIndex2 = array7[2];
			((BoneWeight)(ref val2)).boneIndex3 = array7[3];
			((BoneWeight)(ref val2)).weight0 = array8[0];
			((BoneWeight)(ref val2)).weight1 = array8[1];
			((BoneWeight)(ref val2)).weight2 = array8[2];
			((BoneWeight)(ref val2)).weight3 = array8[3];
			array6[num13] = val2;
		}
		int[] array9 = new int[num2];
		for (int num14 = 0; num14 < num2; num14++)
		{
			array9[num14] = binaryReader.ReadInt32();
			if (array9[num14] < 0 || array9[num14] >= num)
			{
				throw new InvalidDataException("Triangle out of range.");
			}
		}
		if (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length)
		{
			throw new InvalidDataException("Unexpected trailing mesh data.");
		}
		Mesh val3 = new Mesh
		{
			name = "EclipsePlaytestEngineerUnionBuilder",
			indexFormat = (IndexFormat)(num > 65535),
			vertices = array3,
			normals = array4,
			uv = array5,
			boneWeights = array6,
			bindposes = array2,
			triangles = array9
		};
		val3.RecalculateBounds();
		val3.RecalculateTangents();
		return val3;
	}

	private IEnumerator PrepareMineGhosts(SkinDef bodySkin)
	{
		cosmeticStorage = new GameObject("UnionBuilderCosmeticPrefabs");
		cosmeticStorage.SetActive(false);
		Object.DontDestroyOnLoad((Object)(object)cosmeticStorage);
		minePaint = new Texture2D(2, 2, (TextureFormat)4, false);
		minePaint.SetPixels(Enumerable.Repeat<Color>(new Color(0.62f, 0.12f, 0.055f, 0.2f), 4).ToArray());
		minePaint.Apply();
		List<ProjectileGhostReplacement> replacements = new List<ProjectileGhostReplacement>();
		string[] array = new string[2] { "EngiMine", "SpiderMine" };
		foreach (string name in array)
		{
			AsyncOperationHandle<GameObject> h = Addressables.LoadAssetAsync<GameObject>((object)("RoR2/Base/Engi/" + name + ".prefab"));
			retainedAssets.Add(AsyncOperationHandle<GameObject>.op_Implicit(h));
			while (!h.IsDone)
			{
				CheckLoadDeadline(name);
				yield return null;
			}
			if (!Object.op_Implicit((Object)(object)h.Result))
			{
				throw new InvalidOperationException("Missing mine projectile " + name);
			}
			ProjectileController component = h.Result.GetComponent<ProjectileController>();
			GameObject val = component.ghostPrefab;
			if (!Object.op_Implicit((Object)(object)val) && component.ghostPrefabAddress != null && ((AssetReference)component.ghostPrefabAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<GameObject> gh = Addressables.LoadAssetAsync<GameObject>(((AssetReference)component.ghostPrefabAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<GameObject>.op_Implicit(gh));
				while (!gh.IsDone)
				{
					CheckLoadDeadline(name + " ghost");
					yield return null;
				}
				val = gh.Result;
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				throw new InvalidOperationException("Missing mine ghost " + name);
			}
			GameObject val2 = Object.Instantiate<GameObject>(val, cosmeticStorage.transform);
			((Object)val2).name = "EclipseUnionBuilder_" + name + "Ghost";
			val2.SetActive(true);
			SkinnedMeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			foreach (SkinnedMeshRenderer val3 in componentsInChildren)
			{
				((Renderer)val3).sharedMaterials = PaintMine(((Renderer)val3).sharedMaterials);
			}
			replacements.Add(new ProjectileGhostReplacement
			{
				projectilePrefab = h.Result,
				projectileGhostReplacementPrefab = val2,
				ghostReplacementAddress = new AssetReferenceT<GameObject>("")
			});
		}
		bodySkin.skinDefParams.projectileGhostReplacements = replacements.ToArray();
	}

	private Material[] PaintMine(Material[] sources)
	{
		return ((IEnumerable<Material>)sources).Select((Func<Material, Material>)delegate(Material src)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)src))
			{
				return src;
			}
			if (mineMaterials.TryGetValue(src, out var value))
			{
				return value;
			}
			value = new Material(src)
			{
				name = "UnionBuilderMine_" + ((Object)src).name
			};
			value.SetTexture("_MainTex", (Texture)(object)minePaint);
			value.SetColor("_Color", Color.white);
			value.SetFloat("_Smoothness", 0.25f);
			value.SetFloat("_SpecularStrength", 0.3f);
			mineMaterials.Add(src, value);
			return value;
		}).ToArray();
	}

	private Mesh MeshFor(string asset, SkinnedMeshRenderer target)
	{
		string key = asset + "|" + string.Join("|", target.bones.Select((Transform b) => (!Object.op_Implicit((Object)(object)b)) ? "<null>" : ((Object)b).name));
		if (!remappedMeshes.TryGetValue(key, out var value))
		{
			value = ReadMesh(Path.Combine(folder, asset + ".meshbin"), target, target.sharedMesh);
			remappedMeshes.Add(key, value);
		}
		return value;
	}

	private Mesh WristMesh(string asset)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_00b8: 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_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: 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)
		if (wristMeshes.TryGetValue(asset, out var value))
		{
			return value;
		}
		Prepared prepared = this.prepared.Single((Prepared p) => p.BodyName == ((asset == "walker") ? "EngiWalkerTurretBody" : "EngiTurretBody"));
		prepared.Model.GetComponentsInChildren<SkinnedMeshRenderer>(true).Single((SkinnedMeshRenderer x) => x.bones.Length == 15);
		Matrix4x4 val = ((Matrix4x4)(ref prepared.Reference.bindposes[0])).inverse * prepared.Mesh.bindposes[0];
		value = Object.Instantiate<Mesh>(prepared.Mesh);
		Vector3[] vertices = value.vertices;
		Vector3[] normals = value.normals;
		Matrix4x4 inverse = ((Matrix4x4)(ref val)).inverse;
		Matrix4x4 transpose = ((Matrix4x4)(ref inverse)).transpose;
		for (int num = 0; num < vertices.Length; num++)
		{
			vertices[num] = ((Matrix4x4)(ref val)).MultiplyPoint3x4(vertices[num]);
			int num2 = num;
			Vector3 val2 = ((Matrix4x4)(ref transpose)).MultiplyVector(normals[num]);
			normals[num2] = ((Vector3)(ref val2)).normalized;
		}
		value.vertices = vertices;
		value.normals = normals;
		value.RecalculateBounds();
		value.RecalculateTangents();
		wristMeshes.Add(asset, value);
		return value;
	}

	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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_After_Hours_Playtest/HuntressAfterHoursPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressAfterHoursStandalone;

[BepInPlugin("eclipseplaytest.huntress.e3", "Huntress After Hours Playtest", "0.1.5")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressAfterHoursPlaytest : 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 = "eclipseplaytest.huntress.e3";

	public const string Version = "0.1.5";

	private static HuntressAfterHoursPlaytest 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[1]
	{
		new Design("after-hours", "Huntress - After Hours (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E3_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E3_REGISTRATION_BEGIN async loader 0.1.5");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressAfterHoursPlaytest_after-hours"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressAfterHoursPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressAfterHoursPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0f);
			material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressAfterHoursPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressAfterHoursPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E3_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E3_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E3_REGISTERED count=" + additions.Count + " version=0.1.5"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E3_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressAfterHoursPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Beauty_Counter_Playtest/HuntressBeautyCounterPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressBeautyCounterStandalone;

[BepInPlugin("eclipseplaytest.huntress.e7", "Huntress Beauty Counter Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressBeautyCounterPlaytest : 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 = "eclipseplaytest.huntress.e7";

	public const string Version = "0.1.2";

	private static HuntressBeautyCounterPlaytest 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[1]
	{
		new Design("beauty-counter", "Huntress - Beauty Counter (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E7_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E7_REGISTRATION_BEGIN async loader 0.1.2");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressBeautyCounterPlaytest_beauty-counter"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressBeautyCounterPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressBeautyCounterPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.45f);
			material.SetFloat("_SpecularStrength", 1f);
			material.SetFloat("_SpecularExponent", 24f);
			material.SetFloat("_EmPower", 1f);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "emission.png"), linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressBeautyCounterPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressBeautyCounterPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E7_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E7_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E7_REGISTERED count=" + additions.Count + " version=0.1.2"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E7_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressBeautyCounterPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Godhunter_Playtest/HuntressGodhunterPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressGodhunterStandalone;

[BepInPlugin("eclipseplaytest.huntress.e8", "Huntress Godhunter Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressGodhunterPlaytest : 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 = "eclipseplaytest.huntress.e8";

	public const string Version = "0.1.2";

	private static HuntressGodhunterPlaytest 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[1]
	{
		new Design("godhunter", "Huntress - Godhunter (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E8_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E8_REGISTRATION_BEGIN async loader 0.1.2");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressGodhunterPlaytest_godhunter"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressGodhunterPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressGodhunterPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.45f);
			material.SetFloat("_SpecularStrength", 1f);
			material.SetFloat("_SpecularExponent", 24f);
			material.SetFloat("_EmPower", 1f);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "emission.png"), linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressGodhunterPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressGodhunterPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E8_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E8_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E8_REGISTERED count=" + additions.Count + " version=0.1.2"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E8_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressGodhunterPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Headliner_Playtest/HuntressHeadlinerPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressHeadlinerStandalone;

[BepInPlugin("eclipseplaytest.huntress.e4", "Huntress Headliner Playtest", "0.1.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressHeadlinerPlaytest : 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 = "eclipseplaytest.huntress.e4";

	public const string Version = "0.1.3";

	private static HuntressHeadlinerPlaytest 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[1]
	{
		new Design("headliner", "Huntress - Headliner (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E4_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E4_REGISTRATION_BEGIN async loader 0.1.3");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressHeadlinerPlaytest_headliner"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressHeadlinerPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressHeadlinerPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.45f);
			material.SetFloat("_SpecularStrength", 1f);
			material.SetFloat("_SpecularExponent", 24f);
			material.SetFloat("_EmPower", 1f);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "emission.png"), linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressHeadlinerPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressHeadlinerPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E4_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E4_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E4_REGISTERED count=" + additions.Count + " version=0.1.3"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E4_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressHeadlinerPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Liquid_Assets_Playtest/HuntressLiquidAssetsPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressBananaHuntressStandalone;

[BepInPlugin("eclipseplaytest.huntress.e6", "Huntress Banana Huntress Playtest", "0.2.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressLiquidAssetsPlaytest : 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 = "eclipseplaytest.huntress.e6";

	public const string Version = "0.2.2";

	private static HuntressLiquidAssetsPlaytest 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[1]
	{
		new Design("banana-huntress", "Huntress - Banana Huntress (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E6_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E6_REGISTRATION_BEGIN async loader 0.2.2");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressLiquidAssetsPlaytest_liquid-assets"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressLiquidAssetsPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressLiquidAssetsPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			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("skins", design.Slug, "emission.png"), linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressLiquidAssetsPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressLiquidAssetsPlaytest_liquid-assets";
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E6_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E6_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E6_REGISTERED count=" + additions.Count + " version=0.2.2"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E6_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressLiquidAssetsPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Night_Rider_Playtest/HuntressNightRiderPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressNightRiderStandalone;

[BepInPlugin("eclipseplaytest.huntress.e2", "Huntress Night Rider Playtest", "0.1.4")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressNightRiderPlaytest : 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 = "eclipseplaytest.huntress.e2";

	public const string Version = "0.1.4";

	private static HuntressNightRiderPlaytest 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[1]
	{
		new Design("night-rider", "Huntress - Night Rider (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E2_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E2_REGISTRATION_BEGIN async loader 0.1.4");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressNightRiderPlaytest_night-rider"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressNightRiderPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressNightRiderPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0f);
			material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressNightRiderPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressNightRiderPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E2_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E2_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E2_REGISTERED count=" + additions.Count + " version=0.1.4"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E2_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressNightRiderPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Off_Duty_Playtest/HuntressOffDutyPlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressOffDutyStandalone;

[BepInPlugin("eclipseplaytest.huntress.e1", "Huntress Off Duty Playtest", "0.1.5")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressOffDutyPlaytest : 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 = "eclipseplaytest.huntress.e1";

	public const string Version = "0.1.5";

	private static HuntressOffDutyPlaytest 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[1]
	{
		new Design("off-duty", "Huntress - Off Duty (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E1_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E1_REGISTRATION_BEGIN async loader 0.1.5");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressOffDutyPlaytest_off-duty"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressOffDutyPlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressOffDutyPlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.28f);
			material.SetFloat("_SpecularStrength", 0.5f);
			material.SetFloat("_SpecularExponent", 8f);
			material.SetFloat("_EmPower", 0f);
			material.SetTexture("_EmTex", (Texture)(object)Texture2D.blackTexture);
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressOffDutyPlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressOffDutyPlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E1_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E1_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E1_REGISTERED count=" + additions.Count + " version=0.1.5"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E1_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressOffDutyPlaytest",
			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;
	}
}

BepInEx/plugins/Local-Eclipse_Huntress_Skins_Playtest/Local-Huntress_Runway_Sample_Playtest/HuntressRunwaySamplePlaytest.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 HuntressRunwaySampleStandalone;

[BepInPlugin("eclipseplaytest.huntress.e5", "Huntress Runway Sample Playtest", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class HuntressRunwaySamplePlaytest : 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 = "eclipseplaytest.huntress.e5";

	public const string Version = "0.1.2";

	private static HuntressRunwaySamplePlaytest 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[1]
	{
		new Design("runway-sample", "Huntress - Runway Sample (Playtest)", (Color32[])(object)new Color32[4]
		{
			new Color32((byte)86, (byte)91, (byte)78, byte.MaxValue),
			new Color32((byte)42, (byte)47, (byte)51, byte.MaxValue),
			new Color32((byte)151, (byte)160, (byte)160, byte.MaxValue),
			new Color32((byte)60, (byte)153, (byte)146, byte.MaxValue)
		})
	};

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

	[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)("ECLIPSEPLAYTEST_HUNTRESS_E5_REGISTRATION_FAILED: " + ex));
				break;
			}
			if (!flag)
			{
				break;
			}
			yield return null;
		}
		(routine as IDisposable)?.Dispose();
	}

	private IEnumerator RegisterAsync()
	{
		((BaseUnityPlugin)this).Logger.LogInfo((object)"ECLIPSEPLAYTEST_HUNTRESS_E5_REGISTRATION_BEGIN async loader 0.1.2");
		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>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "skinHuntressRunwaySamplePlaytest_runway-sample"))
		{
			yield break;
		}
		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.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		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"));
		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 source = originalInfo.defaultMaterial;
		if (!Object.op_Implicit((Object)(object)source) && 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;
			}
			source = load3.Result;
		}
		if (!Object.op_Implicit((Object)(object)source))
		{
			source = ((Renderer)target).sharedMaterial;
		}
		if (!Object.op_Implicit((Object)(object)source) || !Object.op_Implicit((Object)(object)source.shader))
		{
			throw new InvalidOperationException("Huntress's game shader is unavailable.");
		}
		List<SkinDef> additions = new List<SkinDef>();
		Design[] designs = Designs;
		foreach (Design design in designs)
		{
			string path = Path.Combine(folder, "skins", design.Slug);
			mesh = ReadMesh(Path.Combine(path, "model.meshbin"), target, referenceMesh);
			((Object)mesh).name = "HuntressRunwaySamplePlaytest_" + design.Slug;
			material = new Material(source)
			{
				name = "matHuntressRunwaySamplePlaytest_" + design.Slug
			};
			material.SetTexture("_MainTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "albedo-spec.png"), linear: false));
			material.SetTexture("_NormalTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "normal.png"), linear: true));
			material.SetColor("_Color", Color.white);
			material.SetFloat("_NormalStrength", 0f);
			material.SetFloat("_Smoothness", 0.45f);
			material.SetFloat("_SpecularStrength", 1f);
			material.SetFloat("_SpecularExponent", 24f);
			material.SetFloat("_EmPower", 1f);
			material.SetTexture("_EmTex", (Texture)(object)ReadTexture(Path.Combine("skins", design.Slug, "emission.png"), linear: false));
			material.DisableKeyword("LIMBREMOVAL");
			material.SetFloat("_LimbRemovalOn", 0f);
			RendererInfo val3 = originalInfo;
			val3.defaultMaterial = material;
			val3.defaultMaterialAddress = new AssetReferenceT<Material>("");
			SkinDefParams val4 = ScriptableObject.CreateInstance<SkinDefParams>();
			val4.rendererInfos = (RendererInfo[])(object)new RendererInfo[1] { val3 };
			List<MeshReplacement> list = 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 val5 = new Mesh
				{
					name = "HuntressRunwaySamplePlaytest_hidden_" + ((Object)item).name
				};
				val5.vertices = (Vector3[])(object)new Vector3[0];
				val5.triangles = new int[0];
				list.Add(new MeshReplacement
				{
					renderer = (Renderer)(object)item,
					mesh = val5,
					meshAddress = new AssetReferenceT<Mesh>("")
				});
			}
			val4.meshReplacements = list.ToArray();
			skin = ScriptableObject.CreateInstance<SkinDef>();
			((Object)skin).name = "skinHuntressRunwaySamplePlaytest_" + design.Slug;
			skin.nameToken = "ECLIPSEPLAYTEST_HUNTRESS_E5_" + 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 = val4;
			additions.Add(skin);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E5_PREPARED name=" + design.Name + " vertices=" + mesh.vertexCount + " triangles=" + mesh.triangles.Length / 3 + " unlocked=true"));
			yield return null;
		}
		controller.skins = controller.skins.Concat(additions).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E5_REGISTERED count=" + additions.Count + " version=0.1.2"));
	}

	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))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				ModelSkinController val2 = ((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>();
				val2.skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("ECLIPSEPLAYTEST_HUNTRESS_E5_DISPLAY_READY skins=" + val2.skins.Length));
			}
		}
	}

	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 = "CommandoHuntressRunwaySamplePlaytest",
			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;
	}
}

BepInEx/plugins/MercenaryCanopyCutter/MercenaryCanopyCutter.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMercenaryE3;

[BepInPlugin("eclipseplaytest.mercenary.e3", "Mercenary - Canopy Cutter (Playtest)", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class CanopyCutter : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.mercenary.e3";

	public const string Version = "0.1.0";

	private static CanopyCutter instance;

	private string folder;

	private GameObject modelPrefab;

	private bool registered;

	private float deadline;

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

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

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

	private void CheckDeadline()
	{
		if (Time.realtimeSinceStartup > deadline)
		{
			throw new TimeoutException("Canopy Cutter asset load timed out; continuing startup.");
		}
	}

	private IEnumerator Register()
	{
		GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("MercBody missing");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestMercenaryE3CanopyCutter"))
		{
			yield break;
		}
		SkinDef baseSkin = controller.skins[0];
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op));
			while (!op.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			bp = op.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Mercenary base skin parameters unavailable");
		}
		SkinnedMeshRenderer[] renderers = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		List<RendererInfo> infos = new List<RendererInfo>();
		List<MeshReplacement> replacements = new List<MeshReplacement>();
		string[] array = new string[2] { "body", "sword" };
		foreach (string part in array)
		{
			string expected = ((part == "body") ? "MercMesh" : "MercSwordMesh");
			SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == expected);
			if (target.bones.Length != 93)
			{
				throw new InvalidOperationException(expected + " unexpected bone count");
			}
			Mesh reference = target.sharedMesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
				reference = val2.mesh;
				if (!Object.op_Implicit((Object)(object)reference))
				{
					AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
					retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2));
					while (!op2.IsDone)
					{
						CheckDeadline();
						yield return null;
					}
					reference = op2.Result;
				}
			}
			if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != 93)
			{
				throw new InvalidOperationException(expected + " invalid bind pose");
			}
			RendererInfo info = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material val3 = info.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)val3) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3));
				while (!op3.IsDone)
				{
					CheckDeadline();
					yield return null;
				}
				val3 = op3.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(expected + " no native material");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, part + ".meshbin"), target, reference);
			((Object)val4).name = "EclipseMercenaryE3_" + part;
			Material val5 = new Material(val3)
			{
				name = "matEclipseMercenaryE3_" + part
			};
			val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
			val5.SetColor("_Color", Color.white);
			val5.SetFloat("_NormalStrength", 0f);
			val5.SetFloat("_Smoothness", (part == "sword") ? 0.35f : 0.12f);
			val5.SetFloat("_SpecularStrength", (part == "sword") ? 0.35f : 0.15f);
			val5.SetFloat("_SpecularExponent", 8f);
			val5.SetFloat("_EmPower", (part == "sword") ? 0.85f : 0.35f);
			val5.SetColor("_EmColor", Color.white);
			val5.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			val5.DisableKeyword("FLOWMAP");
			val5.SetFloat("_FlowmapOn", 0f);
			val5.SetFloat("_FlowEmissionStrength", 0f);
			val5.DisableKeyword("FORCE_SPEC");
			val5.SetFloat("_ForceSpecOn", 0f);
			val5.DisableKeyword("LIMBREMOVAL");
			val5.SetFloat("_LimbRemovalOn", 0f);
			info.defaultMaterial = val5;
			info.defaultMaterialAddress = new AssetReferenceT<Material>("");
			infos.Add(info);
			replacements.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MERCENARY_E3_PART_READY " + part + " vertices=" + val4.vertexCount + " bones=" + target.bones.Length));
			yield return null;
		}
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		val6.rendererInfos = infos.ToArray();
		val6.meshReplacements = replacements.ToArray();
		SkinDef val7 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val7).name = "EclipsePlaytestMercenaryE3CanopyCutter";
		val7.nameToken = "ECLIPSE_PLAYTEST_MERCENARY_E3_CANOPY_CUTTER";
		LanguageAPI.Add(val7.nameToken, "Canopy Cutter (Playtest)");
		val7.unlockableDef = null;
		val7.rootObject = modelPrefab;
		val7.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val7.skinDefParams = val6;
		Texture2D val8 = ReadTexture("skin-icon.png", linear: false);
		val7.icon = Sprite.Create(val8, new Rect(0f, 0f, (float)((Texture)val8).width, (float)((Texture)val8).height), new Vector2(0.5f, 0.5f));
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val7 }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"MERCENARY_E3_REGISTERED version=0.1.0 model=M001 unlocked=true");
	}

	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 == "MercBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				(((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>()).skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 93)
		{
			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 = "MercenaryCanopyCutterMesh",
			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;
	}
}

BepInEx/plugins/MercenaryCircuitDuelist/MercenaryCircuitDuelist.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMercenaryE2;

[BepInPlugin("eclipseplaytest.mercenary.e2", "Mercenary - Circuit Duelist (Playtest)", "0.1.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class CircuitDuelist : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.mercenary.e2";

	public const string Version = "0.1.0";

	private static CircuitDuelist instance;

	private string folder;

	private GameObject modelPrefab;

	private bool registered;

	private float deadline;

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

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

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

	private void CheckDeadline()
	{
		if (Time.realtimeSinceStartup > deadline)
		{
			throw new TimeoutException("Circuit Duelist asset load timed out; continuing startup.");
		}
	}

	private IEnumerator Register()
	{
		GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("MercBody missing");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestMercenaryE2CircuitDuelist"))
		{
			yield break;
		}
		SkinDef baseSkin = controller.skins[0];
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op));
			while (!op.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			bp = op.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Mercenary base skin parameters unavailable");
		}
		SkinnedMeshRenderer[] renderers = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		List<RendererInfo> infos = new List<RendererInfo>();
		List<MeshReplacement> replacements = new List<MeshReplacement>();
		string[] array = new string[2] { "body", "sword" };
		foreach (string part in array)
		{
			string expected = ((part == "body") ? "MercMesh" : "MercSwordMesh");
			SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == expected);
			if (target.bones.Length != 93)
			{
				throw new InvalidOperationException(expected + " unexpected bone count");
			}
			Mesh reference = target.sharedMesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
				reference = val2.mesh;
				if (!Object.op_Implicit((Object)(object)reference))
				{
					AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
					retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2));
					while (!op2.IsDone)
					{
						CheckDeadline();
						yield return null;
					}
					reference = op2.Result;
				}
			}
			if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != 93)
			{
				throw new InvalidOperationException(expected + " invalid bind pose");
			}
			RendererInfo info = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material val3 = info.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)val3) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3));
				while (!op3.IsDone)
				{
					CheckDeadline();
					yield return null;
				}
				val3 = op3.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(expected + " no native material");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, part + ".meshbin"), target, reference);
			((Object)val4).name = "EclipseMercenaryE2_" + part;
			Material val5 = new Material(val3)
			{
				name = "matEclipseMercenaryE2_" + part
			};
			val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
			val5.SetColor("_Color", Color.white);
			val5.SetFloat("_NormalStrength", 0f);
			val5.SetFloat("_Smoothness", (part == "sword") ? 0.35f : 0.12f);
			val5.SetFloat("_SpecularStrength", (part == "sword") ? 0.35f : 0.15f);
			val5.SetFloat("_SpecularExponent", 8f);
			val5.SetFloat("_EmPower", (part == "sword") ? 0.85f : 0.35f);
			val5.SetColor("_EmColor", Color.white);
			val5.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			val5.DisableKeyword("FLOWMAP");
			val5.SetFloat("_FlowmapOn", 0f);
			val5.SetFloat("_FlowEmissionStrength", 0f);
			val5.DisableKeyword("FORCE_SPEC");
			val5.SetFloat("_ForceSpecOn", 0f);
			val5.DisableKeyword("LIMBREMOVAL");
			val5.SetFloat("_LimbRemovalOn", 0f);
			info.defaultMaterial = val5;
			info.defaultMaterialAddress = new AssetReferenceT<Material>("");
			infos.Add(info);
			replacements.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MERCENARY_E2_PART_READY " + part + " vertices=" + val4.vertexCount + " bones=" + target.bones.Length));
			yield return null;
		}
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		val6.rendererInfos = infos.ToArray();
		val6.meshReplacements = replacements.ToArray();
		SkinDef val7 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val7).name = "EclipsePlaytestMercenaryE2CircuitDuelist";
		val7.nameToken = "ECLIPSE_PLAYTEST_MERCENARY_E2_CIRCUIT_DUELIST";
		LanguageAPI.Add(val7.nameToken, "Circuit Duelist (Playtest)");
		val7.unlockableDef = null;
		val7.rootObject = modelPrefab;
		val7.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val7.skinDefParams = val6;
		Texture2D val8 = ReadTexture("skin-icon.png", linear: false);
		val7.icon = Sprite.Create(val8, new Rect(0f, 0f, (float)((Texture)val8).width, (float)((Texture)val8).height), new Vector2(0.5f, 0.5f));
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val7 }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"MERCENARY_E2_REGISTERED version=0.1.0 model=M001 unlocked=true");
	}

	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 == "MercBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				(((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>()).skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 93)
		{
			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 = "MercenaryCircuitDuelistMesh",
			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;
	}
}

BepInEx/plugins/MercenaryRoadwornRonin/MercenaryRoadwornRonin.dll

Decompiled 3 hours 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.Text;
using BepInEx;
using HG.Reflection;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.UI.MainMenu;
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 EclipsePlaytestMercenaryE1;

[BepInPlugin("eclipseplaytest.mercenary.e1", "Mercenary - Roadworn Ronin (Playtest)", "0.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class RoadwornRonin : BaseUnityPlugin
{
	public const string Guid = "eclipseplaytest.mercenary.e1";

	public const string Version = "0.1.2";

	private static RoadwornRonin instance;

	private string folder;

	private GameObject modelPrefab;

	private bool registered;

	private float deadline;

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

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

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

	private void CheckDeadline()
	{
		if (Time.realtimeSinceStartup > deadline)
		{
			throw new TimeoutException("Roadworn Ronin asset load timed out; continuing startup.");
		}
	}

	private IEnumerator Register()
	{
		GameObject val = BodyCatalog.FindBodyPrefab("MercBody");
		if (!Object.op_Implicit((Object)(object)val))
		{
			throw new InvalidOperationException("MercBody missing");
		}
		modelPrefab = ((Component)val.GetComponent<ModelLocator>().modelTransform).gameObject;
		ModelSkinController controller = modelPrefab.GetComponent<ModelSkinController>();
		if (controller.skins.Any((SkinDef s) => Object.op_Implicit((Object)(object)s) && ((Object)s).name == "EclipsePlaytestMercenaryE1RoadwornRonin"))
		{
			yield break;
		}
		SkinDef baseSkin = controller.skins[0];
		SkinDefParams bp = baseSkin.skinDefParams;
		if (!Object.op_Implicit((Object)(object)bp) && baseSkin.skinDefParamsAddress != null && ((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKeyIsValid())
		{
			AsyncOperationHandle<SkinDefParams> op = Addressables.LoadAssetAsync<SkinDefParams>(((AssetReference)baseSkin.skinDefParamsAddress).RuntimeKey);
			retainedAssets.Add(AsyncOperationHandle<SkinDefParams>.op_Implicit(op));
			while (!op.IsDone)
			{
				CheckDeadline();
				yield return null;
			}
			bp = op.Result;
		}
		if (!Object.op_Implicit((Object)(object)bp))
		{
			throw new InvalidOperationException("Mercenary base skin parameters unavailable");
		}
		SkinnedMeshRenderer[] renderers = modelPrefab.GetComponentsInChildren<SkinnedMeshRenderer>(true);
		List<RendererInfo> infos = new List<RendererInfo>();
		List<MeshReplacement> replacements = new List<MeshReplacement>();
		string[] array = new string[2] { "body", "sword" };
		foreach (string part in array)
		{
			string expected = ((part == "body") ? "MercMesh" : "MercSwordMesh");
			SkinnedMeshRenderer target = renderers.Single((SkinnedMeshRenderer r) => ((Object)r).name == expected);
			if (target.bones.Length != 93)
			{
				throw new InvalidOperationException(expected + " unexpected bone count");
			}
			Mesh reference = target.sharedMesh;
			if (!Object.op_Implicit((Object)(object)reference))
			{
				MeshReplacement val2 = bp.meshReplacements.First((MeshReplacement r) => (Object)(object)r.renderer == (Object)(object)target);
				reference = val2.mesh;
				if (!Object.op_Implicit((Object)(object)reference))
				{
					AsyncOperationHandle<Mesh> op2 = Addressables.LoadAssetAsync<Mesh>(((AssetReference)val2.meshAddress).RuntimeKey);
					retainedAssets.Add(AsyncOperationHandle<Mesh>.op_Implicit(op2));
					while (!op2.IsDone)
					{
						CheckDeadline();
						yield return null;
					}
					reference = op2.Result;
				}
			}
			if (!Object.op_Implicit((Object)(object)reference) || reference.bindposes.Length != 93)
			{
				throw new InvalidOperationException(expected + " invalid bind pose");
			}
			RendererInfo info = bp.rendererInfos.First((RendererInfo r) => (Object)(object)r.renderer == (Object)(object)target);
			Material val3 = info.defaultMaterial;
			if (!Object.op_Implicit((Object)(object)val3) && info.defaultMaterialAddress != null && ((AssetReference)info.defaultMaterialAddress).RuntimeKeyIsValid())
			{
				AsyncOperationHandle<Material> op3 = Addressables.LoadAssetAsync<Material>(((AssetReference)info.defaultMaterialAddress).RuntimeKey);
				retainedAssets.Add(AsyncOperationHandle<Material>.op_Implicit(op3));
				while (!op3.IsDone)
				{
					CheckDeadline();
					yield return null;
				}
				val3 = op3.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(expected + " no native material");
			}
			Mesh val4 = ReadMesh(Path.Combine(folder, part + ".meshbin"), target, reference);
			((Object)val4).name = "EclipseMercenaryE1_" + part;
			Material val5 = new Material(val3)
			{
				name = "matEclipseMercenaryE1_" + part
			};
			val5.SetTexture("_MainTex", (Texture)(object)ReadTexture("albedo-spec.png", linear: false));
			val5.SetTexture("_NormalTex", (Texture)(object)ReadTexture("normal.png", linear: true));
			val5.SetColor("_Color", Color.white);
			val5.SetFloat("_NormalStrength", 0f);
			val5.SetFloat("_Smoothness", (part == "sword") ? 0.35f : 0.12f);
			val5.SetFloat("_SpecularStrength", (part == "sword") ? 0.35f : 0.15f);
			val5.SetFloat("_SpecularExponent", 8f);
			val5.SetFloat("_EmPower", (part == "sword") ? 0.85f : 0.35f);
			val5.SetColor("_EmColor", Color.white);
			val5.SetTexture("_EmTex", (Texture)(object)ReadTexture("emission.png", linear: false));
			val5.DisableKeyword("FLOWMAP");
			val5.SetFloat("_FlowmapOn", 0f);
			val5.SetFloat("_FlowEmissionStrength", 0f);
			val5.DisableKeyword("FORCE_SPEC");
			val5.SetFloat("_ForceSpecOn", 0f);
			val5.DisableKeyword("LIMBREMOVAL");
			val5.SetFloat("_LimbRemovalOn", 0f);
			info.defaultMaterial = val5;
			info.defaultMaterialAddress = new AssetReferenceT<Material>("");
			infos.Add(info);
			replacements.Add(new MeshReplacement
			{
				renderer = (Renderer)(object)target,
				mesh = val4,
				meshAddress = new AssetReferenceT<Mesh>("")
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MERCENARY_E1_PART_READY " + part + " vertices=" + val4.vertexCount + " bones=" + target.bones.Length));
			yield return null;
		}
		SkinDefParams val6 = ScriptableObject.CreateInstance<SkinDefParams>();
		val6.rendererInfos = infos.ToArray();
		val6.meshReplacements = replacements.ToArray();
		SkinDef val7 = ScriptableObject.CreateInstance<SkinDef>();
		((Object)val7).name = "EclipsePlaytestMercenaryE1RoadwornRonin";
		val7.nameToken = "ECLIPSE_PLAYTEST_MERCENARY_E1_ROADWORN_RONIN";
		LanguageAPI.Add(val7.nameToken, "Roadworn Ronin (Playtest)");
		val7.unlockableDef = null;
		val7.rootObject = modelPrefab;
		val7.baseSkins = (SkinDef[])(object)new SkinDef[1] { baseSkin };
		val7.skinDefParams = val6;
		Texture2D val8 = ReadTexture("skin-icon.png", linear: false);
		val7.icon = Sprite.Create(val8, new Rect(0f, 0f, (float)((Texture)val8).width, (float)((Texture)val8).height), new Vector2(0.5f, 0.5f));
		controller.skins = controller.skins.Concat((IEnumerable<SkinDef>)(object)new SkinDef[1] { val7 }).ToArray();
		registered = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"MERCENARY_E1_REGISTERED version=0.1.2 model=M006 unlocked=true");
	}

	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 == "MercBody"));
		if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.displayPrefab))
		{
			CharacterModel componentInChildren = val.displayPrefab.GetComponentInChildren<CharacterModel>(true);
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				(((Component)componentInChildren).GetComponent<ModelSkinController>() ?? ((Component)componentInChildren).gameObject.AddComponent<ModelSkinController>()).skins = (SkinDef[])modelPrefab.GetComponent<ModelSkinController>().skins.Clone();
			}
		}
	}

	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)) != "PWE1")
		{
			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 != 93)
		{
			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 = "MercenaryRoadwornRoninMesh",
			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;
	}
}