Decompiled source of MoreCosmetics v0.2.1

MoreCosmetics.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MoreCosmetics")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+36b9a642cd89b916ddfb6db721b685b1ffd7dd33")]
[assembly: AssemblyProduct("MoreCosmetics")]
[assembly: AssemblyTitle("MoreCosmetics")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MoreCosmetics
{
	[BepInPlugin("justresearch.morecosmetics", "More Cosmetics", "0.2.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "justresearch.morecosmetics";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("justresearch.morecosmetics").PatchAll();
			Log.LogInfo((object)"More Cosmetics loaded");
		}
	}
	[Serializable]
	internal class CosmeticData
	{
		public string name;

		public string displayName;

		public string kind;

		public int order;

		public float[] positions;

		public float[] normals;

		public float[] uv0;

		public float[] slot;

		public float[] uv3;

		public int[] triangles;

		public int[] bones;

		public float[] weights;
	}
	internal static class Cosmetics
	{
		private const int HeadBone = 1;

		public static readonly List<(CosmeticData data, Mesh mesh)> Loaded = new List<(CosmeticData, Mesh)>();

		public static void LoadAll(Mesh template)
		{
			if (Loaded.Count > 0)
			{
				return;
			}
			Matrix4x4[] bindposes = GetBindposes(template);
			Assembly assembly = typeof(Cosmetics).Assembly;
			foreach (string item in from r in assembly.GetManifestResourceNames()
				where r.StartsWith("Cosmetics.")
				select r)
			{
				try
				{
					using StreamReader streamReader = new StreamReader(assembly.GetManifestResourceStream(item));
					CosmeticData cosmeticData = JsonUtility.FromJson<CosmeticData>(streamReader.ReadToEnd());
					Loaded.Add((cosmeticData, Build(cosmeticData, bindposes)));
				}
				catch (Exception arg)
				{
					Plugin.Log.LogError((object)$"Couldn't load {item}: {arg}");
				}
			}
			Loaded.Sort(((CosmeticData data, Mesh mesh) a, (CosmeticData data, Mesh mesh) b) => a.data.order.CompareTo(b.data.order));
		}

		private static Matrix4x4[] GetBindposes(Mesh template)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Matrix4x4[] array = (Object.op_Implicit((Object)(object)template) ? template.bindposes : null);
				if (array != null && array.Length > 1)
				{
					Plugin.Log.LogInfo((object)("Using bind poses from '" + ((Object)template).name + "'"));
					return array;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Couldn't read bind poses from '" + ((template != null) ? ((Object)template).name : null) + "': " + ex.Message));
			}
			Matrix4x4 val = default(Matrix4x4);
			((Matrix4x4)(ref val))..ctor(new Vector4(1f, 0f, 0f, 0f), new Vector4(0f, 0f, 1f, 0f), new Vector4(0f, -1f, 0f, 0f), new Vector4(0f, 0f, 1.09f, 1f));
			Matrix4x4[] array2 = Enumerable.Repeat<Matrix4x4>(Matrix4x4.identity, 18).ToArray();
			array2[1] = ((Matrix4x4)(ref val)).inverse;
			Plugin.Log.LogInfo((object)"Using measured head bind pose");
			return array2;
		}

		private static Mesh Build(CosmeticData d, Matrix4x4[] bindposes)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Expected O, but got Unknown
			int num = d.positions.Length / 3;
			Vector3[] array = (Vector3[])(object)new Vector3[num];
			Vector3[] array2 = (Vector3[])(object)new Vector3[num];
			Vector2[] array3 = (Vector2[])(object)new Vector2[num];
			Vector2[] array4 = (Vector2[])(object)new Vector2[num];
			Vector2[] array5 = (Vector2[])(object)new Vector2[num];
			Vector2[] array6 = (Vector2[])(object)new Vector2[num];
			Color[] array7 = (Color[])(object)new Color[num];
			BoneWeight[] array8 = (BoneWeight[])(object)new BoneWeight[num];
			bool flag = d.bones != null && d.bones.Length == 2 * num && d.weights != null && d.weights.Length == 2 * num;
			for (int i = 0; i < num; i++)
			{
				array[i] = new Vector3(0f - d.positions[3 * i], d.positions[3 * i + 1], d.positions[3 * i + 2]);
				array2[i] = new Vector3(0f - d.normals[3 * i], d.normals[3 * i + 1], d.normals[3 * i + 2]);
				array3[i] = new Vector2(d.uv0[2 * i], d.uv0[2 * i + 1]);
				array4[i] = new Vector2(0.01f, 0.01f);
				array5[i] = new Vector2(d.slot[i], 0f);
				array6[i] = new Vector2(d.uv3[2 * i], d.uv3[2 * i + 1]);
				array7[i] = Color.white;
				int num2 = i;
				BoneWeight val;
				BoneWeight val2;
				if (!flag)
				{
					val = default(BoneWeight);
					((BoneWeight)(ref val)).boneIndex0 = 1;
					((BoneWeight)(ref val)).weight0 = 1f;
					val2 = val;
				}
				else
				{
					val = default(BoneWeight);
					((BoneWeight)(ref val)).boneIndex0 = d.bones[2 * i];
					((BoneWeight)(ref val)).weight0 = d.weights[2 * i];
					((BoneWeight)(ref val)).boneIndex1 = d.bones[2 * i + 1];
					((BoneWeight)(ref val)).weight1 = d.weights[2 * i + 1];
					val2 = val;
				}
				array8[num2] = val2;
			}
			int[] array9 = new int[d.triangles.Length];
			for (int j = 0; j < array9.Length; j += 3)
			{
				array9[j] = d.triangles[j];
				array9[j + 1] = d.triangles[j + 2];
				array9[j + 2] = d.triangles[j + 1];
			}
			Mesh val3 = new Mesh
			{
				name = "MoreCosmetics_" + d.name
			};
			if (num > 65000)
			{
				val3.indexFormat = (IndexFormat)1;
			}
			val3.vertices = array;
			val3.normals = array2;
			val3.SetUVs(0, array3);
			val3.SetUVs(1, array4);
			val3.SetUVs(2, array5);
			val3.SetUVs(3, array6);
			val3.colors = array7;
			val3.triangles = array9;
			val3.boneWeights = array8;
			val3.bindposes = bindposes;
			val3.RecalculateBounds();
			val3.RecalculateTangents();
			Plugin.Log.LogInfo((object)$"Built {d.kind} '{d.displayName}' ({array9.Length / 3} triangles)");
			return val3;
		}
	}
	[HarmonyPatch(typeof(SkinManager), "Awake")]
	internal static class RegisterPatch
	{
		private static void Postfix()
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			Cosmetics.LoadAll(SkinManager._allHats.Select((OutfitMeshInfo h) => (h == null) ? null : h.Mesh).FirstOrDefault((Func<Mesh, bool>)((Mesh m) => Object.op_Implicit((Object)(object)m))));
			foreach (var item2 in Cosmetics.Loaded)
			{
				CosmeticData item = item2.data;
				Mesh mesh = item2.mesh;
				List<OutfitMeshInfo> list = item.kind switch
				{
					"hat" => SkinManager._allHats, 
					"accessory" => SkinManager._allAccessories, 
					"outfit" => SkinManager._allOutfits, 
					_ => null, 
				};
				if (list == null)
				{
					Plugin.Log.LogWarning((object)("Unknown cosmetic kind '" + item.kind + "' for " + item.name));
				}
				else if (!list.Any((OutfitMeshInfo i) => (Object)(object)((i != null) ? i.Mesh : null) == (Object)(object)mesh))
				{
					list.Add(new OutfitMeshInfo(mesh, true));
					Plugin.Log.LogInfo((object)$"Added {item.kind} '{item.displayName}' at index {list.Count - 1}");
				}
			}
			SkinManager.SeenHats = Grow(SkinManager.SeenHats, SkinManager._allHats.Count);
			SkinManager.SeenOutfits = Grow(SkinManager.SeenOutfits, SkinManager._allOutfits.Count);
			SkinManager.SeenAccesories = Grow(SkinManager.SeenAccesories, SkinManager._allAccessories.Count);
		}

		private static bool[] Grow(bool[] a, int size)
		{
			if (a == null)
			{
				return new bool[size];
			}
			if (a.Length < size)
			{
				Array.Resize(ref a, size);
			}
			return a;
		}
	}
	[HarmonyPatch(typeof(LocalSkin), "EnablePreview")]
	internal static class BoneCheckPatch
	{
		private static bool _checked;

		private static void Postfix()
		{
			LocalSkin instance = LocalSkin._instance;
			if (!_checked && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance._hatRenderer))
			{
				_checked = true;
				Transform[] bones = instance._hatRenderer.bones;
				string text = ((bones.Length > 1 && Object.op_Implicit((Object)(object)bones[1])) ? ((Object)bones[1]).name : "missing");
				if (text == "Head")
				{
					Plugin.Log.LogInfo((object)"Hat renderer bone 1 is Head, as expected");
				}
				else
				{
					Plugin.Log.LogWarning((object)("Hat renderer bone 1 is '" + text + "', not Head - custom hats may sit in the wrong place"));
				}
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}