Decompiled source of NailongAvatar v1.4.1

plugins/NailongAvatar/NailongSwap.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using GTFO.API;
using GameData;
using Gear;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using Player;
using RigTools;
using SNetwork;
using TMPro;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[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 LocalSuteraSwap
{
	internal static class ArmRetargeting
	{
		internal static Quaternion MirrorRotation(Quaternion rotation)
		{
			return new Quaternion(rotation.X, 0f - rotation.Y, 0f - rotation.Z, rotation.W);
		}

		internal static Vector3 MirrorDirection(Vector3 direction)
		{
			return new Vector3(0f - direction.X, direction.Y, direction.Z);
		}

		internal static Quaternion FromBind(Quaternion bindRotation, Vector3 bindDirection, Vector3 targetDirection)
		{
			Vector3 vector = Vector3.Normalize(bindDirection);
			Vector3 vector2 = Vector3.Normalize(targetDirection);
			float num = Math.Clamp(Vector3.Dot(vector, vector2), -1f, 1f);
			Quaternion quaternion;
			if (num < -0.9999f)
			{
				Vector3 value = Vector3.Cross(vector, Vector3.UnitY);
				if (value.LengthSquared() < 0.0001f)
				{
					value = Vector3.Cross(vector, Vector3.UnitZ);
				}
				quaternion = Quaternion.CreateFromAxisAngle(Vector3.Normalize(value), (float)Math.PI);
			}
			else
			{
				quaternion = Quaternion.Normalize(new Quaternion(Vector3.Cross(vector, vector2), 1f + num));
			}
			return Quaternion.Normalize(quaternion * bindRotation);
		}

		internal static Quaternion FollowChest(Quaternion chest, Quaternion bindChest, Quaternion bindBone)
		{
			return Quaternion.Normalize(chest * Quaternion.Inverse(bindChest) * bindBone);
		}

		internal static void ClearTorso(Vector3 shoulder, Vector3 upper, Vector3 lower, float upperLength, float lowerLength, float side, out Vector3 elbow, out Vector3 wrist)
		{
			Vector3 vector = Downward(upper, side, (0.52f - shoulder.X * side) / upperLength);
			elbow = shoulder + vector * upperLength;
			Vector3 vector2 = Downward(lower, side, (0.54f - elbow.X * side) / lowerLength);
			float num = MathF.Acos(Math.Clamp(Vector3.Dot(vector, vector2), -1f, 1f));
			if (num > 0.43633232f)
			{
				float num2 = 0.43633232f / num;
				vector2 = Vector3.Normalize((MathF.Sin((1f - num2) * num) * vector + MathF.Sin(num2 * num) * vector2) / MathF.Sin(num));
			}
			wrist = elbow + vector2 * lowerLength;
		}

		private static Vector3 Downward(Vector3 desired, float side, float minimumOutward)
		{
			if (desired.LengthSquared() > 1E-06f)
			{
				desired = Vector3.Normalize(desired);
			}
			float num = Math.Clamp(MathF.Max(desired.X * side, minimumOutward), 0.15f, 0.85f);
			float num2 = Math.Clamp(desired.Z, -0.2f, 0.2f);
			return new Vector3(side * num, 0f - MathF.Sqrt(1f - num * num - num2 * num2), num2);
		}
	}
	internal sealed class AttachmentBudget
	{
		private int lastFrame = -1;

		internal bool TryAcquire(int frame)
		{
			if (lastFrame == frame)
			{
				return false;
			}
			lastFrame = frame;
			return true;
		}
	}
	internal sealed class AvatarData
	{
		public Texture2D SurfaceAtlas;

		public Shader SheenShader;

		public Shader ToonShader;

		private AssetBundle toonBundle;

		private static AssetBundle sharedToonBundle;

		private static int toonUsers;

		private bool toonLoaded;

		private AssetBundle materialBundle;

		public readonly Dictionary<string, Rect> MaterialRegions = new Dictionary<string, Rect>();

		public Texture2D StockingMatcap;

		public Texture2D CrystalMatcap;

		public Node[] Nodes;

		internal readonly Dictionary<int, Vector3> PalmDirections = new Dictionary<int, Vector3>();

		public Part[] Renderers;

		public bool[] ArmNodes;

		public bool[] FPSNodes;

		private readonly Dictionary<string, Texture2D> textures = new Dictionary<string, Texture2D>();

		private readonly List<Material> materials = new List<Material>();

		internal bool SharedResourcesAlive
		{
			get
			{
				//IL_000e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Expected O, but got Unknown
				if ((!toonLoaded || Ic.B((Object)ToonShader)) && materials.All((Material m) => Ic.B((Object)m) && Ic.B((Object)m.shader)))
				{
					return textures.Values.All((Texture2D t) => Ic.B((Object)t));
				}
				return false;
			}
		}

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

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

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

		private static T[] Read<T>(BinaryReader r, Func<T> read)
		{
			int num = r.ReadInt32();
			if (num < 0 || num > 4000000)
			{
				throw new InvalidDataException("Invalid array length");
			}
			T[] array = new T[num];
			for (int i = 0; i < num; i++)
			{
				array[i] = read();
			}
			return array;
		}

		public static AvatarData Load(string path)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0321: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0364: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Expected O, but got Unknown
			//IL_03b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Expected O, but got Unknown
			//IL_0786: Unknown result type (might be due to invalid IL or missing references)
			//IL_078d: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0801: Unknown result type (might be due to invalid IL or missing references)
			//IL_080b: Expected O, but got Unknown
			//IL_0836: Unknown result type (might be due to invalid IL or missing references)
			//IL_0840: Expected O, but got Unknown
			//IL_081e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0825: Unknown result type (might be due to invalid IL or missing references)
			//IL_0853: Unknown result type (might be due to invalid IL or missing references)
			//IL_085a: Unknown result type (might be due to invalid IL or missing references)
			AvatarData data = new AvatarData();
			string text = Path.Combine(Path.GetDirectoryName(path), "nailong-liltoon.bundle");
			if (File.Exists(text))
			{
				try
				{
					if (!Ic.B((Object)sharedToonBundle))
					{
						sharedToonBundle = AssetBundle.LoadFromFile(text);
					}
					data.toonBundle = sharedToonBundle;
					if (Ic.B((Object)data.toonBundle))
					{
						toonUsers++;
					}
					if (!Ic.B((Object)data.toonBundle))
					{
						throw new InvalidDataException("lilToon bundle failed");
					}
					foreach (Object item in (Il2CppArrayBase<Object>)(object)data.toonBundle.LoadAllAssets(Il2CppType.Of<Shader>()))
					{
						Shader val = ((Il2CppObjectBase)item).TryCast<Shader>();
						if (Ic.B((Object)val) && ((Object)val).name == "Hidden/lilToonCutout")
						{
							data.ToonShader = val;
						}
					}
					if (!Ic.B((Object)data.ToonShader) || !data.ToonShader.isSupported)
					{
						throw new InvalidDataException("lilToon shader unsupported");
					}
					data.toonLoaded = true;
					Shader toonShader = data.ToonShader;
					((Object)toonShader).hideFlags = (HideFlags)(((Object)toonShader).hideFlags | 0x3D);
					AssetBundle val2 = data.toonBundle;
					((Object)val2).hideFlags = (HideFlags)(((Object)val2).hideFlags | 0x3D);
					Plugin.Logger.LogInfo((object)("SUTERA_LILTOON_LOADED shader=" + ((Object)data.ToonShader).name));
				}
				catch (Exception ex)
				{
					data.ToonShader = null;
					Plugin.Logger.LogWarning((object)("SUTERA_LILTOON_FALLBACK " + ex.Message));
				}
			}
			string path2 = Path.Combine(Path.GetDirectoryName(path), "surface-atlas.png");
			if (File.Exists(path2))
			{
				Texture2D val3 = new Texture2D(2, 2, (TextureFormat)4, true, true);
				if (!ImageConversion.LoadImage(val3, Ic.A(File.ReadAllBytes(path2)), false))
				{
					throw new InvalidDataException("Surface atlas failed to load");
				}
				data.SurfaceAtlas = val3;
				data.textures["surface-atlas.png"] = val3;
			}
			string directoryName = Path.GetDirectoryName(path);
			string path3 = Path.Combine(directoryName, "material-regions.bin");
			string text2 = Path.Combine(directoryName, "sutera-materials.bundle");
			if (File.Exists(path3) && File.Exists(text2))
			{
				try
				{
					using (BinaryReader binaryReader = new BinaryReader(File.OpenRead(path3)))
					{
						if (binaryReader.ReadString() != "SUTERA_MATERIAL_REGIONS")
						{
							throw new InvalidDataException("Material region header");
						}
						int num = binaryReader.ReadInt32();
						if (num < 0 || num > 1000)
						{
							throw new InvalidDataException("Material region count");
						}
						for (int i = 0; i < num; i++)
						{
							data.MaterialRegions.Add(binaryReader.ReadString(), new Rect(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle()));
						}
					}
					data.materialBundle = AssetBundle.LoadFromFile(text2);
					if (!Ic.B((Object)data.materialBundle))
					{
						throw new InvalidDataException("Material bundle could not be loaded");
					}
					data.SheenShader = ((Il2CppObjectBase)data.materialBundle.LoadAsset("Assets/Shaders/MatcapSheen.shader", Il2CppType.Of<Shader>())).TryCast<Shader>();
					if (!Ic.B((Object)data.SheenShader) || !data.SheenShader.isSupported)
					{
						throw new InvalidDataException("MatCap shader unsupported");
					}
					data.StockingMatcap = data.ReadTexture(Path.Combine(directoryName, "stockings-matcap.png"));
					data.CrystalMatcap = data.ReadTexture(Path.Combine(directoryName, "crystal-matcap.png"));
					Plugin.Logger.LogInfo((object)("MATERIAL_DETAILS_LOADED shader=" + ((Object)data.SheenShader).name + " regions=" + data.MaterialRegions.Count));
				}
				catch (Exception ex2)
				{
					data.SheenShader = null;
					Plugin.Logger.LogWarning((object)("Material details unavailable; stable GTFO material retained: " + ex2.Message));
				}
			}
			BinaryReader r = new BinaryReader(File.OpenRead(path));
			try
			{
				if (r.ReadString() != "GTFOAVATAR" || r.ReadInt32() != 1)
				{
					throw new InvalidDataException("Unknown avatar format");
				}
				r.ReadString();
				data.Nodes = Read(r, () => new Node
				{
					Name = r.ReadString(),
					Parent = r.ReadInt32(),
					Position = Vec(r),
					Rotation = Quat(r),
					Scale = Vec(r),
					Human = r.ReadInt32(),
					WorldRotation = Quat(r),
					WorldPosition = Vec(r)
				});
				Dictionary<string, int> dictionary = data.Nodes.Where((Node n) => n.Human >= 0).ToDictionary((Node n) => BoneBase(n.Name), (Node n) => n.Human);
				Node[] nodes = data.Nodes;
				int value = 0;
				Node[] array = nodes;
				foreach (Node node in array)
				{
					if (node.Human < 0 && dictionary.TryGetValue(BoneBase(node.Name), out value))
					{
						node.Human = value;
					}
				}
				data.ArmNodes = new bool[data.Nodes.Length];
				data.FPSNodes = new bool[data.Nodes.Length];
				for (int num3 = 0; num3 < data.Nodes.Length; num3++)
				{
					for (int num4 = num3; num4 >= 0; num4 = data.Nodes[num4].Parent)
					{
						int human = data.Nodes[num4].Human;
						if (human == 13 || human == 14)
						{
							data.ArmNodes[num3] = true;
							break;
						}
					}
				}
				for (int num5 = 0; num5 < data.Nodes.Length; num5++)
				{
					int num6 = num5;
					bool flag = false;
					bool flag2 = false;
					while (num6 >= 0)
					{
						int human2 = data.Nodes[num6].Human;
						if (human2 == 10 || human2 == 9)
						{
							flag2 = true;
							break;
						}
						if (human2 >= 0)
						{
							flag = true;
						}
						num6 = data.Nodes[num6].Parent;
					}
					data.FPSNodes[num5] = flag && !flag2;
				}
				data.Renderers = Read(r, () => new Part
				{
					Name = r.ReadString(),
					Transform = r.ReadInt32(),
					Skinned = r.ReadBoolean(),
					Vertices = Read(r, () => Vec(r)),
					Normals = Read(r, () => Vec(r)),
					UV = Read(r, (Func<Vector2>)(() => new Vector2(r.ReadSingle(), r.ReadSingle()))),
					Tangents = Read(r, (Func<Vector4>)(() => new Vector4(r.ReadSingle(), r.ReadSingle(), r.ReadSingle(), r.ReadSingle()))),
					Colors = Read(r, () => Col(r)),
					Weights = Read(r, delegate
					{
						//IL_0002: Unknown result type (might be due to invalid IL or missing references)
						//IL_0098: Unknown result type (might be due to invalid IL or missing references)
						BoneWeight result = default(BoneWeight);
						((BoneWeight)(ref result)).boneIndex0 = r.ReadInt32();
						((BoneWeight)(ref result)).boneIndex1 = r.ReadInt32();
						((BoneWeight)(ref result)).boneIndex2 = r.ReadInt32();
						((BoneWeight)(ref result)).boneIndex3 = r.ReadInt32();
						((BoneWeight)(ref result)).weight0 = r.ReadSingle();
						((BoneWeight)(ref result)).weight1 = r.ReadSingle();
						((BoneWeight)(ref result)).weight2 = r.ReadSingle();
						((BoneWeight)(ref result)).weight3 = r.ReadSingle();
						return result;
					}),
					Bindposes = Read(r, delegate
					{
						//IL_0002: 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)
						Matrix4x4 result = default(Matrix4x4);
						for (int j = 0; j < 16; j++)
						{
							((Matrix4x4)(ref result))[j] = r.ReadSingle();
						}
						return result;
					}),
					Bones = Read(r, () => r.ReadInt32()),
					RootBone = r.ReadInt32(),
					Bounds = new Bounds(Vec(r), Vec(r)),
					Surfaces = Read(r, delegate
					{
						//IL_0041: Unknown result type (might be due to invalid IL or missing references)
						//IL_0046: Unknown result type (might be due to invalid IL or missing references)
						//IL_0049: Unknown result type (might be due to invalid IL or missing references)
						//IL_006e: Unknown result type (might be due to invalid IL or missing references)
						//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
						//IL_00ce: Expected O, but got Unknown
						//IL_00de: Unknown result type (might be due to invalid IL or missing references)
						//IL_00e8: Expected O, but got Unknown
						//IL_0104: Unknown result type (might be due to invalid IL or missing references)
						//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
						//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
						//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
						//IL_01ba: Expected O, but got Unknown
						//IL_0158: Unknown result type (might be due to invalid IL or missing references)
						//IL_015f: Expected O, but got Unknown
						Surface surface = new Surface
						{
							Triangles = Read(r, () => r.ReadInt32())
						};
						string text3 = r.ReadString();
						string text4 = r.ReadString();
						Color color = Col(r);
						Vector2 mainTextureScale = default(Vector2);
						((Vector2)(ref mainTextureScale))..ctor(r.ReadSingle(), r.ReadSingle());
						Vector2 mainTextureOffset = default(Vector2);
						((Vector2)(ref mainTextureOffset))..ctor(r.ReadSingle(), r.ReadSingle());
						int num7 = r.ReadInt32();
						float num8 = r.ReadSingle();
						int num9 = r.ReadInt32();
						Shader val5 = Shader.Find("Standard");
						if (!Ic.B((Object)val5))
						{
							throw new InvalidOperationException("Standard shader unavailable");
						}
						surface.Material = new Material(val5);
						((Object)surface.Material).name = text3 + "_GTFO";
						surface.Material.color = color;
						surface.Material.SetFloat("_Glossiness", 0.1f);
						surface.Material.SetFloat("_Metallic", 0f);
						if (!string.IsNullOrEmpty(text4))
						{
							Texture2D value2 = null;
							if (!data.textures.TryGetValue(text4, out value2))
							{
								value2 = new Texture2D(2, 2, (TextureFormat)4, true);
								if (!ImageConversion.LoadImage(value2, Ic.A(File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(path), text4))), false))
								{
									throw new InvalidDataException("Texture failed: " + text4);
								}
								data.textures[text4] = value2;
							}
							surface.Material.mainTexture = (Texture)value2;
						}
						surface.Material.mainTextureScale = mainTextureScale;
						surface.Material.mainTextureOffset = mainTextureOffset;
						surface.Material.SetInt("_Cull", num9);
						if (num7 == 1)
						{
							surface.Material.SetFloat("_Mode", 1f);
							surface.Material.SetFloat("_Cutoff", num8);
							surface.Material.SetInt("_SrcBlend", 1);
							surface.Material.SetInt("_DstBlend", 0);
							surface.Material.SetInt("_ZWrite", 1);
							surface.Material.EnableKeyword("_ALPHATEST_ON");
							surface.Material.SetOverrideTag("RenderType", "TransparentCutout");
							surface.Material.renderQueue = 2450;
						}
						data.materials.Add(surface.Material);
						return surface;
					})
				});
				if (r.BaseStream.Position != r.BaseStream.Length)
				{
					throw new InvalidDataException("Unexpected avatar bytes");
				}
			}
			finally
			{
				if (r != null)
				{
					((IDisposable)r).Dispose();
				}
			}
			foreach (Material material in data.materials)
			{
				((Object)material).hideFlags = (HideFlags)(((Object)material).hideFlags | 0x3D);
			}
			foreach (Texture2D value3 in data.textures.Values)
			{
				((Object)value3).hideFlags = (HideFlags)(((Object)value3).hideFlags | 0x3D);
			}
			if (Ic.B((Object)data.SheenShader))
			{
				Shader sheenShader = data.SheenShader;
				((Object)sheenShader).hideFlags = (HideFlags)(((Object)sheenShader).hideFlags | 0x3D);
			}
			if (Ic.B((Object)data.materialBundle))
			{
				AssetBundle val4 = data.materialBundle;
				((Object)val4).hideFlags = (HideFlags)(((Object)val4).hideFlags | 0x3D);
			}
			return data;
		}

		private Texture2D ReadTexture(string path)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true, false);
			textures[path] = val;
			if (!ImageConversion.LoadImage(val, Ic.A(File.ReadAllBytes(path)), false))
			{
				throw new InvalidDataException("Texture failed: " + Path.GetFileName(path));
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return val;
		}

		public void Dispose()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Expected O, but got Unknown
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			Part[] renderers = Renderers;
			foreach (Part part in renderers)
			{
				if (Ic.B((Object)part.BodyMesh))
				{
					Object.Destroy((Object)part.BodyMesh);
				}
				if (Ic.B((Object)part.ArmsMesh))
				{
					Object.Destroy((Object)part.ArmsMesh);
				}
			}
			foreach (Material material in materials)
			{
				if (Ic.B((Object)material))
				{
					Object.Destroy((Object)material);
				}
			}
			foreach (Texture2D value in textures.Values)
			{
				if (Ic.B((Object)value))
				{
					Object.Destroy((Object)value);
				}
			}
			if (Ic.B((Object)materialBundle))
			{
				materialBundle.Unload(true);
			}
			if (Ic.B((Object)toonBundle))
			{
				toonBundle = null;
				if (--toonUsers == 0)
				{
					sharedToonBundle.Unload(true);
					sharedToonBundle = null;
				}
			}
		}

		private static string BoneBase(string name)
		{
			int num = name.IndexOf('(');
			if (num >= 0)
			{
				name = name.Substring(0, num);
			}
			return new string(name.ToLowerInvariant().Where(char.IsLetterOrDigit).ToArray());
		}
	}
	internal static class Compatibility
	{
		private const BindingFlags Static = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		private const BindingFlags Instance = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static Type manukaOutfit;

		private static Type manukaDriver;

		private static bool ownSelection;

		internal static void Initialize(Harmony harmony)
		{
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Expected O, but got Unknown
			manukaOutfit = (from a in AppDomain.CurrentDomain.GetAssemblies()
				select a.GetType("LocalAvatarSwap.ManukaOutfit", throwOnError: false)).FirstOrDefault((Type t) => t != null);
			if (!(manukaOutfit == null))
			{
				manukaDriver = manukaOutfit.Assembly.GetType("LocalAvatarSwap.Driver");
				harmony.Patch((MethodBase)manukaOutfit.GetMethod("Choose", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Compatibility), "ManukaChoice", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)manukaOutfit.GetMethod("Receive", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), new HarmonyMethod(typeof(Compatibility), "ManukaReceive", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Logger.LogInfo((object)"SUTERA_COEXIST MANUKA wardrobe compatibility installed; independent player selections remain.");
			}
		}

		private static void ManukaChoice(bool __0)
		{
			if (__0 && !ownSelection)
			{
				SuteraOutfit.ClearLocalForManuka();
			}
		}

		private static void ManukaReceive(ulong __0, byte[] __1)
		{
			if (__1 != null && __1.Length == 3 && __1[0] == 1 && __1[2] == 1)
			{
				SuteraOutfit.ClearRemoteForManuka(__0);
			}
		}

		internal static void OnSelectingSutera()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (manukaOutfit == null || ownSelection)
			{
				return;
			}
			ownSelection = true;
			try
			{
				object value = manukaOutfit.GetField("previews", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				((IDictionary)((value is IDictionary) ? value : null))?.Clear();
				SNet_Player localPlayer = SNet.LocalPlayer;
				if ((Object)localPlayer != (Object)null)
				{
					ReleaseOther(localPlayer.Lookup);
				}
				manukaOutfit.GetMethod("Choose", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).Invoke(null, new object[1] { false });
			}
			finally
			{
				ownSelection = false;
			}
		}

		internal static void OnRemoteSutera(ulong lookup)
		{
			if (!(manukaOutfit == null))
			{
				object value = manukaOutfit.GetField("remote", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null);
				IDictionary dictionary = (IDictionary)((value is IDictionary) ? value : null);
				if (dictionary != null)
				{
					dictionary[lookup] = false;
				}
				ReleaseOther(lookup);
			}
		}

		private static bool Includes(SNet_Player owner, ulong lookup)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if ((Object)owner == (Object)null)
			{
				return false;
			}
			if (owner.Lookup == lookup)
			{
				return true;
			}
			SNet_Player master = SNet.Master;
			if (owner.IsBot && (Object)master != (Object)null)
			{
				return master.Lookup == lookup;
			}
			return false;
		}

		internal static void ReleaseSutera(ulong lookup)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			Driver instance = Driver.Instance;
			if (!Ic.B((Object)instance))
			{
				return;
			}
			IEnumerable obj = typeof(Driver).GetField("rigs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(instance) as IEnumerable;
			List<GameObject> list = new List<GameObject>();
			foreach (Rig item in obj)
			{
				if (Includes(item.NetworkOwner, lookup) && Ic.B((Object)item.RenderRoot))
				{
					list.Add(item.RenderRoot);
				}
			}
			foreach (GameObject item2 in list)
			{
				instance.RestoreRoot(item2);
			}
		}

		private static void ReleaseOther(ulong lookup)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			Type type = manukaDriver;
			object obj;
			if (type == null)
			{
				obj = null;
			}
			else
			{
				FieldInfo field = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				obj = ((field != null) ? field.GetValue(null) : null);
			}
			object obj2 = obj;
			if (obj2 == null)
			{
				return;
			}
			IEnumerable obj3 = manukaDriver.GetField("rigs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(obj2) as IEnumerable;
			List<GameObject> list = new List<GameObject>();
			foreach (object item in obj3)
			{
				Type type2 = item.GetType();
				object value = type2.GetField("NetworkOwner", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item);
				SNet_Player owner = (SNet_Player)((value is SNet_Player) ? value : null);
				object value2 = type2.GetField("RenderRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item);
				GameObject val = (GameObject)((value2 is GameObject) ? value2 : null);
				if (Includes(owner, lookup) && Ic.B((Object)val))
				{
					list.Add(val);
				}
			}
			MethodInfo method = manukaDriver.GetMethod("RestoreRoot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (GameObject item2 in list)
			{
				method.Invoke(obj2, new object[1] { item2 });
			}
		}
	}
	public sealed class Driver : MonoBehaviour
	{
		internal static Driver Instance;

		private readonly Dictionary<int, AvatarData> datas = new Dictionary<int, AvatarData>();

		private readonly List<Rig> rigs = new List<Rig>();

		private readonly Dictionary<int, float> rejected = new Dictionary<int, float>();

		private float nextScan;

		private readonly AttachmentBudget attachmentBudget = new AttachmentBudget();

		private bool failed;

		private float nextConfig;

		private readonly EquipmentSettlement equipmentSettlement = new EquipmentSettlement();

		private bool gameplayView;

		private float performanceAt;

		private int performanceFrames;

		private double animationMilliseconds;

		private double fpsAnimationMilliseconds;

		private double fpsAnimationMaximum;

		private int fpsAnimationSamples;

		private float nextFpsReport = 30f;

		private long updateAllocated;

		private long animationAllocated;

		private float worstFrame;

		private PlayerAgent[] cachedPlayers = (PlayerAgent[])(object)new PlayerAgent[0];

		private CM_PlayerLobbyBar[] cachedLobby = (CM_PlayerLobbyBar[])(object)new CM_PlayerLobbyBar[0];

		private double worstUpdate;

		private double worstDiscovery;

		private double previousUpdate;

		private int previousGc0;

		private int previousGc1;

		private int previousGc2;

		public Driver(IntPtr p)
			: base(p)
		{
		}

		internal void RestoreRoot(GameObject root, bool waitForEquipment = true)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_0068: Expected O, but got Unknown
			if (waitForEquipment)
			{
				equipmentSettlement.Changed(((Object)root).GetInstanceID(), Time.unscaledTime);
			}
			else
			{
				equipmentSettlement.Selected(((Object)root).GetInstanceID());
			}
			nextScan = 0f;
			for (int num = rigs.Count - 1; num >= 0; num--)
			{
				if ((Object)rigs[num].RenderRoot == (Object)root)
				{
					Plugin.Logger.LogDebug((object)("AVATAR_REMOVE reason=native-equip arms=" + rigs[num].Arms));
					rigs[num].Dispose();
					rigs.RemoveAt(num);
				}
			}
		}

		internal void RefreshOutfit()
		{
			nextScan = 0f;
		}

		public void Update()
		{
			long timestamp = Stopwatch.GetTimestamp();
			long allocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
			try
			{
				UpdateCore();
			}
			finally
			{
				previousUpdate = (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency;
				worstUpdate = Math.Max(worstUpdate, previousUpdate);
				updateAllocated += GC.GetAllocatedBytesForCurrentThread() - allocatedBytesForCurrentThread;
			}
		}

		private void UpdateCore()
		{
			//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Expected O, but got Unknown
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b8: Expected O, but got Unknown
			//IL_06e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Expected O, but got Unknown
			//IL_075c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0766: Expected O, but got Unknown
			//IL_08da: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e4: Expected O, but got Unknown
			//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ab: Expected O, but got Unknown
			//IL_08f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_08fa: Expected O, but got Unknown
			//IL_0939: Unknown result type (might be due to invalid IL or missing references)
			//IL_0943: Expected O, but got Unknown
			//IL_0912: Unknown result type (might be due to invalid IL or missing references)
			//IL_091c: Expected O, but got Unknown
			//IL_083c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0846: Expected O, but got Unknown
			//IL_0856: Unknown result type (might be due to invalid IL or missing references)
			//IL_0860: Expected O, but got Unknown
			Hotkeys.Poll();
			Instance = this;
			if (Time.unscaledTime >= nextConfig)
			{
				nextConfig = Time.unscaledTime + 1f;
				SuteraOutfit.Tick();
				string path = Path.Combine(Plugin.Folder, "reload.request");
				if (File.Exists(path))
				{
					File.Delete(path);
					foreach (Rig rig in rigs)
					{
						rig.Dispose();
					}
					rigs.Clear();
					rejected.Clear();
					foreach (AvatarData value in datas.Values)
					{
						value.Dispose();
					}
					datas.Clear();
					failed = false;
					Plugin.Logger.LogInfo((object)"Avatar resources reset for live diagnostic reload.");
				}
			}
			if (Hotkeys.Pressed((KeyCode)288))
			{
				Plugin.Enabled.Value = !Plugin.Enabled.Value;
				Plugin.Logger.LogInfo((object)("Replacement enabled: " + Plugin.Enabled.Value));
			}
			if (Hotkeys.Pressed((KeyCode)285))
			{
				Plugin.SecondaryMotion.Value = !Plugin.SecondaryMotion.Value;
				Plugin.Logger.LogInfo((object)("SUTERA_SECONDARY_MOTION enabled=" + Plugin.SecondaryMotion.Value));
			}
			if (Hotkeys.Pressed((KeyCode)287))
			{
				Plugin.UseLilToon.Value = !Plugin.UseLilToon.Value;
				foreach (Rig rig2 in rigs)
				{
					rig2.Dispose();
				}
				rigs.Clear();
				rejected.Clear();
				nextScan = 0f;
				Plugin.Logger.LogInfo((object)("SUTERA_LILTOON enabled=" + Plugin.UseLilToon.Value));
			}
			if (Hotkeys.Pressed((KeyCode)286))
			{
				Plugin.StockingDetails.Value = !Plugin.StockingDetails.Value;
				Plugin.Logger.LogInfo((object)("Stocking fabric sheen: " + Plugin.StockingDetails.Value));
			}
			if (Hotkeys.Pressed((KeyCode)290))
			{
				Plugin.FirstPerson.Value = !Plugin.FirstPerson.Value;
				nextScan = 0f;
				Plugin.Logger.LogInfo((object)("First person global switch: " + Plugin.FirstPerson.Value + "; per-outfit settings preserved."));
			}
			if (Hotkeys.Pressed((KeyCode)289))
			{
				string text = Path.Combine(Plugin.Folder, "in-game-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".png");
				ScreenCapture.CaptureScreenshot(text);
				Plugin.Logger.LogInfo((object)("Screenshot requested: " + text));
				foreach (Rig rig3 in rigs)
				{
					DiagnoseSafely(rig3);
				}
			}
			for (int num = rigs.Count - 1; num >= 0; num--)
			{
				if (!rigs[num].Valid || !Plugin.Enabled.Value || (!Plugin.AllPlayers.Value && Ic.B((Object)rigs[num].Owner) && !((Agent)rigs[num].Owner).IsLocallyOwned) || (rigs[num].Arms && (!Plugin.FirstPerson.Value || !Plugin.OutfitUsesFirstPerson(rigs[num].Outfit))))
				{
					Plugin.Logger.LogDebug((object)("AVATAR_REMOVE reason=invalid-or-disabled arms=" + rigs[num].Arms));
					rigs[num].Dispose();
					rigs.RemoveAt(num);
				}
			}
			if (!Plugin.Enabled.Value || failed || Time.unscaledTime < nextScan)
			{
				return;
			}
			nextScan = Time.unscaledTime + 1f;
			try
			{
				gameplayView = false;
				foreach (Camera item in (Il2CppArrayBase<Camera>)(object)Camera.allCameras)
				{
					if (Ic.B((Object)item) && ((Behaviour)item).isActiveAndEnabled && ((Component)item).gameObject.activeInHierarchy && ((Object)item).name == "FPSLookCamera")
					{
						gameplayView = true;
						break;
					}
				}
				for (int num2 = rigs.Count - 1; num2 >= 0; num2--)
				{
					if (rigs[num2].Arms && !gameplayView)
					{
						Plugin.Logger.LogDebug((object)"AVATAR_REMOVE reason=no-gameplay-camera");
						rigs[num2].Dispose();
						rigs.RemoveAt(num2);
					}
				}
				for (int num3 = rigs.Count - 1; num3 >= 0; num3--)
				{
					if (!SuteraOutfit.ShouldUse(rigs[num3].NetworkOwner, rigs[num3].RenderRoot))
					{
						rigs[num3].Dispose();
						rigs.RemoveAt(num3);
					}
				}
				bool flag = false;
				foreach (AvatarData value2 in datas.Values)
				{
					if (!value2.SharedResourcesAlive)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					foreach (Rig rig4 in rigs)
					{
						rig4.Dispose();
					}
					rigs.Clear();
					rejected.Clear();
					foreach (AvatarData value3 in datas.Values)
					{
						value3.Dispose();
					}
					datas.Clear();
					Plugin.Logger.LogWarning((object)"AVATAR_RESOURCE_RECOVERY cached Unity assets expired; reload on next selected player.");
				}
				long timestamp = Stopwatch.GetTimestamp();
				List<PlayerAgent> playerAgentsInLevel = PlayerManager.PlayerAgentsInLevel;
				cachedPlayers = ((playerAgentsInLevel != null) ? Ic.A2<PlayerAgent>(playerAgentsInLevel.ToArray()) : Array.Empty<PlayerAgent>());
				CM_PageLoadout current2 = CM_PageLoadout.Current;
				Il2CppReferenceArray<CM_PlayerLobbyBar> val = (Ic.B((Object)current2) ? current2.m_playerLobbyBars : null);
				cachedLobby = ((val != null) ? ((IEnumerable<CM_PlayerLobbyBar>)val).ToArray() : Array.Empty<CM_PlayerLobbyBar>());
				worstDiscovery = Math.Max(worstDiscovery, (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency);
				PlayerAgent[] array = cachedPlayers;
				foreach (PlayerAgent val2 in array)
				{
					if (!Ic.B((Object)val2) || (!Plugin.AllPlayers.Value && !((Agent)val2).IsLocallyOwned))
					{
						continue;
					}
					GameObject renderRoot = ((val2.RigSwitch != null && val2.RigSwitch.m_data != null) ? val2.RigSwitch.m_data.m_rootObject : (Ic.B((Object)val2.PlayerSyncModel) ? ((Component)val2.PlayerSyncModel).gameObject : null));
					int num4 = SuteraOutfit.OutfitOf(val2.Owner);
					if (num4 < 0)
					{
						continue;
					}
					Attach(val2, val2.AnimatorBody, arms: false, renderRoot, val2.Owner, num4);
					if (gameplayView && ((Agent)val2).IsLocallyOwned && Plugin.FirstPerson.Value && Plugin.OutfitUsesFirstPerson(num4))
					{
						FirstPersonItemHolder fPItemHolder = val2.FPItemHolder;
						PlayerFPSBody val3 = (Ic.B((Object)fPItemHolder) ? fPItemHolder.FPSArms : null);
						if (Ic.B((Object)val3))
						{
							GameObject renderRoot2 = ((val3.m_rigSwitch != null && val3.m_rigSwitch.m_data != null) ? val3.m_rigSwitch.m_data.m_rootObject : val3.m_modelRoot);
							Attach(val2, val3.m_anim, arms: true, renderRoot2, val2.Owner, num4);
						}
					}
				}
				CM_PlayerLobbyBar[] array2 = cachedLobby;
				foreach (CM_PlayerLobbyBar val4 in array2)
				{
					if (Ic.B((Object)val4) && Ic.B((Object)val4.m_playerModel) && (Plugin.AllPlayers.Value || (Ic.B((Object)val4.m_player) && val4.m_player.IsLocal)))
					{
						Animator animator = (Ic.B((Object)val4.m_playerAnim) ? val4.m_playerAnim : val4.m_playerModel.GetComponentInChildren<Animator>());
						GameObject renderRoot3 = ((val4.m_rigSwitch != null && val4.m_rigSwitch.m_data != null) ? val4.m_rigSwitch.m_data.m_rootObject : val4.m_playerModel);
						int num5 = SuteraOutfit.OutfitOf(val4.m_player);
						if (num5 >= 0)
						{
							Attach(null, animator, arms: false, renderRoot3, val4.m_player, num5);
						}
					}
				}
			}
			catch (Exception ex)
			{
				failed = true;
				Plugin.Logger.LogError((object)("Avatar load failed; original models retained: " + ex));
			}
		}

		private void Attach(PlayerAgent owner, Animator animator, bool arms, GameObject renderRoot, SNet_Player networkOwner, int outfit)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00e3: Expected O, but got Unknown
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Expected O, but got Unknown
			//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ec: Expected O, but got Unknown
			//IL_0313: Unknown result type (might be due to invalid IL or missing references)
			//IL_031e: Expected O, but got Unknown
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Expected O, but got Unknown
			if (!Ic.B((Object)animator) || !((Component)animator).gameObject.activeInHierarchy || !Ic.B((Object)renderRoot) || !renderRoot.activeInHierarchy)
			{
				return;
			}
			if (!equipmentSettlement.Ready(((Object)renderRoot).GetInstanceID(), Time.unscaledTime))
			{
				nextScan = 0f;
				return;
			}
			Rig rig = rigs.FirstOrDefault((Rig x) => (Object)x.Animator == (Object)animator);
			if (rig != null)
			{
				bool flag = (Object)rig.NetworkOwner != (Object)null && (Object)networkOwner != (Object)null && rig.NetworkOwner.Lookup == networkOwner.Lookup;
				if (rig.Installed && (Object)rig.RenderRoot == (Object)renderRoot && flag && rig.Outfit == outfit)
				{
					return;
				}
			}
			int instanceID = ((Object)animator).GetInstanceID();
			float value = 0f;
			if (rejected.TryGetValue(instanceID, out value) && Time.unscaledTime < value)
			{
				return;
			}
			if (!attachmentBudget.TryAcquire(Time.frameCount))
			{
				nextScan = 0f;
				return;
			}
			try
			{
				if (!datas.TryGetValue(outfit, out var value2))
				{
					int num = Mathf.Clamp(outfit, 0, Plugin.OutfitFiles.Length - 1);
					string text = Plugin.OutfitFiles[num];
					value2 = AvatarData.Load(Path.Combine(Plugin.Folder, text));
					datas[outfit] = value2;
					Plugin.Logger.LogInfo((object)("AVATAR_LOADED outfit=" + outfit + " file=" + text + " nodes=" + value2.Nodes.Length + " renderers=" + value2.Renderers.Length));
					nextScan = 0f;
					return;
				}
				if (rig != null)
				{
					rig.Dispose();
					rigs.Remove(rig);
					Plugin.Logger.LogDebug((object)"AVATAR_REATTACH reason=renderer-root-owner-or-outfit-changed");
				}
				Rig rig2 = new Rig(value2, owner, animator, arms, renderRoot, outfit);
				rig2.NetworkOwner = networkOwner;
				rigs.Add(rig2);
				rejected.Remove(instanceID);
				Plugin.Logger.LogDebug((object)("AVATAR_ATTACHED slot=" + (Ic.B((Object)owner) ? owner.PlayerSlotIndex.ToString() : "lobby") + " arms=" + arms + " mappedBones=" + rig2.MappingCount + " player_lookup=" + (((Object)networkOwner != (Object)null) ? networkOwner.Lookup.ToString() : "none") + " bot=" + ((Object)networkOwner != (Object)null && networkOwner.IsBot) + " local=" + ((Object)networkOwner != (Object)null && networkOwner.IsLocal)));
			}
			catch (Exception ex)
			{
				rejected[instanceID] = Time.unscaledTime + 5f;
				Plugin.Logger.LogWarning((object)("Avatar attachment skipped; original model retained: " + ex.Message));
			}
		}

		public void LateUpdate()
		{
			long timestamp = Stopwatch.GetTimestamp();
			long allocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
			foreach (Rig rig in rigs)
			{
				try
				{
					if (rig.Valid)
					{
						long num = (rig.Arms ? Stopwatch.GetTimestamp() : 0);
						rig.Animate();
						if (rig.Arms)
						{
							double num2 = (double)(Stopwatch.GetTimestamp() - num) * 1000.0 / (double)Stopwatch.Frequency;
							fpsAnimationMilliseconds += num2;
							fpsAnimationMaximum = Math.Max(fpsAnimationMaximum, num2);
							fpsAnimationSamples++;
						}
					}
				}
				catch (Exception ex)
				{
					rig.Dispose();
					Plugin.Logger.LogWarning((object)("Retargeting stopped: " + ex.Message));
				}
			}
			animationMilliseconds += (double)(Stopwatch.GetTimestamp() - timestamp) * 1000.0 / (double)Stopwatch.Frequency;
			animationAllocated += GC.GetAllocatedBytesForCurrentThread() - allocatedBytesForCurrentThread;
			performanceFrames++;
			if (Time.unscaledTime >= nextFpsReport)
			{
				if (fpsAnimationSamples > 0)
				{
					Plugin.Logger.LogInfo((object)("AVATAR_FPS_COST cpu_avg_ms=" + (fpsAnimationMilliseconds / (double)fpsAnimationSamples).ToString("F3") + " cpu_max_ms=" + fpsAnimationMaximum.ToString("F3") + " samples=" + fpsAnimationSamples + " toon=" + FirstPersonRendering.UseToon(arms: true, Plugin.UseLilToon.Value, Plugin.FirstPersonLilToon.Value)));
				}
				fpsAnimationMilliseconds = (fpsAnimationMaximum = 0.0);
				fpsAnimationSamples = 0;
				nextFpsReport = Time.unscaledTime + 30f;
			}
			worstFrame = Math.Max(worstFrame, Time.unscaledDeltaTime * 1000f);
			if (Time.unscaledTime >= performanceAt + 10f)
			{
				float num3 = Time.unscaledTime - performanceAt;
				int num4 = GC.CollectionCount(0);
				int num5 = GC.CollectionCount(1);
				int num6 = GC.CollectionCount(2);
				Plugin.Logger.LogDebug((object)("AVATAR_PERFORMANCE fps=" + ((float)performanceFrames / num3).ToString("F1") + " retarget_ms=" + (animationMilliseconds / (double)Math.Max(1, performanceFrames)).ToString("F3") + " worst_frame_ms=" + worstFrame.ToString("F1") + " update_max_ms=" + worstUpdate.ToString("F2") + " discovery_max_ms=" + worstDiscovery.ToString("F2") + " update_bytes_frame=" + updateAllocated / Math.Max(1, performanceFrames) + " animate_bytes_frame=" + animationAllocated / Math.Max(1, performanceFrames) + " managed_gc=" + (num4 - previousGc0) + "," + (num5 - previousGc1) + "," + (num6 - previousGc2) + " enabled=" + Plugin.Enabled.Value + " rigs=" + rigs.Count));
				updateAllocated = 0L;
				animationAllocated = 0L;
				previousGc0 = num4;
				previousGc1 = num5;
				previousGc2 = num6;
				worstUpdate = 0.0;
				worstDiscovery = 0.0;
				performanceAt = Time.unscaledTime;
				performanceFrames = 0;
				animationMilliseconds = 0.0;
				worstFrame = 0f;
			}
		}

		private static void DiagnoseSafely(Rig rig)
		{
			try
			{
				rig.Diagnose();
			}
			catch (Exception ex)
			{
				Plugin.Logger.LogWarning((object)("Avatar diagnostics unavailable: " + ex.Message));
			}
		}

		public void OnDestroy()
		{
			foreach (Rig rig in rigs)
			{
				rig.Dispose();
			}
			rigs.Clear();
			foreach (AvatarData value in datas.Values)
			{
				value.Dispose();
			}
			datas.Clear();
		}
	}
	internal sealed class EquipmentSettlement
	{
		private readonly Dictionary<int, float> readyAt = new Dictionary<int, float>();

		internal void Changed(int root, float now)
		{
			readyAt[root] = now + 0.1f;
		}

		internal void Selected(int root)
		{
			readyAt.Remove(root);
		}

		internal bool Ready(int root, float now)
		{
			if (!readyAt.TryGetValue(root, out var value))
			{
				return true;
			}
			if (now < value)
			{
				return false;
			}
			readyAt.Remove(root);
			return true;
		}
	}
	internal static class FirstPersonRendering
	{
		internal static bool UseToon(bool arms, bool enabled, bool firstPersonEnabled)
		{
			if (enabled)
			{
				return !arms || firstPersonEnabled;
			}
			return false;
		}
	}
	internal sealed class FpsDiscoveryBudget
	{
		private int attempts;

		private float nextAttempt;

		internal bool TryAcquire(float now)
		{
			if (attempts >= 3 || now < nextAttempt)
			{
				return false;
			}
			attempts++;
			nextAttempt = now + 2f;
			return true;
		}
	}
	internal static class Hotkeys
	{
		private static readonly bool[] held = new bool[6];

		private static readonly bool[] pressed = new bool[6];

		private static readonly uint processId = (uint)Process.GetCurrentProcess().Id;

		private static bool nativeAvailable = true;

		private static bool unityAvailable = true;

		[DllImport("user32.dll")]
		private static extern short GetAsyncKeyState(int key);

		[DllImport("user32.dll")]
		private static extern IntPtr GetForegroundWindow();

		[DllImport("user32.dll")]
		private static extern uint GetWindowThreadProcessId(IntPtr window, out uint id);

		internal static void Poll()
		{
			bool flag = Application.isFocused;
			if (nativeAvailable)
			{
				try
				{
					GetWindowThreadProcessId(GetForegroundWindow(), out var id);
					flag = id == processId;
				}
				catch (Exception ex)
				{
					nativeAvailable = false;
					Plugin.Logger.LogWarning((object)("Native hotkey fallback unavailable: " + ex.Message));
				}
			}
			for (int i = 0; i < held.Length; i++)
			{
				bool flag2 = false;
				if (flag && unityAvailable)
				{
					try
					{
						flag2 = Input.GetKey((KeyCode)(285 + i));
					}
					catch (Exception ex2)
					{
						unityAvailable = false;
						Plugin.Logger.LogWarning((object)("Unity hotkeys unavailable; using Windows: " + ex2.Message));
					}
				}
				if (flag && nativeAvailable)
				{
					try
					{
						flag2 |= (GetAsyncKeyState(115 + i) & 0x8000) != 0;
					}
					catch (Exception)
					{
						nativeAvailable = false;
					}
				}
				pressed[i] = flag2 && !held[i];
				held[i] = flag2;
				if (pressed[i])
				{
					Plugin.Logger.LogInfo((object)("AVATAR_HOTKEY F" + (i + 4)));
				}
			}
		}

		internal static bool Pressed(KeyCode key)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return pressed[key - 285];
		}
	}
	internal static class Ic
	{
		public static bool B(Object o)
		{
			return o != (Object)null;
		}

		public static Il2CppStructArray<T> A<T>(T[] src) where T : unmanaged
		{
			return Il2CppStructArray<T>.op_Implicit(src);
		}

		public static Il2CppReferenceArray<T> R<T>(T[] src) where T : Il2CppObjectBase
		{
			return Il2CppReferenceArray<T>.op_Implicit(src);
		}

		public static Action<T> D<T>(Action<T> src)
		{
			return Action<T>.op_Implicit(src);
		}

		public static T[] A2<T>(Il2CppArrayBase<T> src)
		{
			return Il2CppArrayBase<T>.op_Implicit(src);
		}
	}
	internal sealed class Node
	{
		public string Name;

		public int Parent;

		public int Human;

		public Vector3 Position;

		public Vector3 Scale;

		public Vector3 WorldPosition;

		public Quaternion Rotation;

		public Quaternion WorldRotation;
	}
	internal static class OutfitSelection
	{
		internal static bool Changed(bool wasSelected, int previousIndex, bool selected, int index)
		{
			if (wasSelected == selected)
			{
				if (selected)
				{
					return previousIndex != index;
				}
				return false;
			}
			return true;
		}
	}
	internal sealed class Part
	{
		public string Name;

		public int Transform;

		public int RootBone;

		public bool Skinned;

		public int[] Bones;

		public BoneWeight[] Weights;

		public Vector3[] Vertices;

		public Vector3[] Normals;

		public Vector2[] UV;

		public Vector4[] Tangents;

		public Color[] Colors;

		public Matrix4x4[] Bindposes;

		public Bounds Bounds;

		public Surface[] Surfaces;

		public Mesh BodyMesh;

		public Mesh ArmsMesh;

		public int[] FPSBones;

		public Mesh Build(bool arms, bool[] armNodes)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Expected O, but got Unknown
			//IL_0359: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: 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_051b: Unknown result type (might be due to invalid IL or missing references)
			if (arms && Ic.B((Object)ArmsMesh))
			{
				return ArmsMesh;
			}
			if (!arms && Ic.B((Object)BodyMesh))
			{
				return BodyMesh;
			}
			if (arms && !Skinned)
			{
				return null;
			}
			int[][] array = Surfaces.Select((Surface s) => (!arms) ? s.Triangles : FilterArms(s.Triangles, armNodes)).ToArray();
			if (array.All((int[] t) => t.Length == 0))
			{
				return null;
			}
			int[] array2 = (arms ? (from i in array.SelectMany((int[] t) => t).Distinct()
				orderby i
				select i).ToArray() : Enumerable.Range(0, Vertices.Length).ToArray());
			int[] vertexRemap = new int[Vertices.Length];
			for (int num = 0; num < array2.Length; num++)
			{
				vertexRemap[array2[num]] = num;
			}
			BoneWeight[] array3 = (BoneWeight[])(Skinned ? ((Array)array2.Select((int i) => Weights[i]).ToArray()) : ((Array)new BoneWeight[0]));
			int[] array4 = Enumerable.Range(0, Bones.Length).ToArray();
			if (arms)
			{
				HashSet<int> hashSet = new HashSet<int>();
				BoneWeight[] array5 = array3;
				for (int num2 = 0; num2 < array5.Length; num2++)
				{
					BoneWeight val = array5[num2];
					if (((BoneWeight)(ref val)).weight0 > 0f)
					{
						hashSet.Add(((BoneWeight)(ref val)).boneIndex0);
					}
					if (((BoneWeight)(ref val)).weight1 > 0f)
					{
						hashSet.Add(((BoneWeight)(ref val)).boneIndex1);
					}
					if (((BoneWeight)(ref val)).weight2 > 0f)
					{
						hashSet.Add(((BoneWeight)(ref val)).boneIndex2);
					}
					if (((BoneWeight)(ref val)).weight3 > 0f)
					{
						hashSet.Add(((BoneWeight)(ref val)).boneIndex3);
					}
				}
				array4 = hashSet.OrderBy((int i) => i).ToArray();
				int[] array6 = new int[Bones.Length];
				for (int num3 = 0; num3 < array4.Length; num3++)
				{
					array6[array4[num3]] = num3;
				}
				for (int num4 = 0; num4 < array3.Length; num4++)
				{
					BoneWeight val2 = array3[num4];
					((BoneWeight)(ref val2)).boneIndex0 = array6[((BoneWeight)(ref val2)).boneIndex0];
					((BoneWeight)(ref val2)).boneIndex1 = array6[((BoneWeight)(ref val2)).boneIndex1];
					((BoneWeight)(ref val2)).boneIndex2 = array6[((BoneWeight)(ref val2)).boneIndex2];
					((BoneWeight)(ref val2)).boneIndex3 = array6[((BoneWeight)(ref val2)).boneIndex3];
					array3[num4] = val2;
				}
				FPSBones = array4.Select((int i) => Bones[i]).ToArray();
			}
			Mesh val3 = new Mesh();
			((Object)val3).name = Name + (arms ? "_FPS" : "_Body");
			((Object)val3).hideFlags = (HideFlags)(((Object)val3).hideFlags | 0x3D);
			val3.indexFormat = (IndexFormat)(array2.Length > 65535);
			val3.vertices = Ic.A<Vector3>(array2.Select((int i) => Vertices[i]).ToArray());
			if (Normals.Length == Vertices.Length)
			{
				val3.normals = Ic.A<Vector3>(array2.Select((int i) => Normals[i]).ToArray());
			}
			if (UV.Length == Vertices.Length)
			{
				val3.uv = Ic.A<Vector2>(array2.Select((int i) => UV[i]).ToArray());
			}
			if (Tangents.Length == Vertices.Length)
			{
				val3.tangents = Ic.A<Vector4>(array2.Select((int i) => Tangents[i]).ToArray());
			}
			if (Colors.Length == Vertices.Length)
			{
				val3.colors = Ic.A<Color>(array2.Select((int i) => Colors[i]).ToArray());
			}
			if (Skinned)
			{
				val3.boneWeights = Ic.A<BoneWeight>(array3);
				val3.bindposes = Ic.A<Matrix4x4>(array4.Select((int i) => Bindposes[i]).ToArray());
			}
			val3.subMeshCount = Surfaces.Length;
			for (int num5 = 0; num5 < array.Length; num5++)
			{
				val3.SetTriangles(Ic.A(arms ? array[num5].Select((int v) => vertexRemap[v]).ToArray() : array[num5]), num5, false);
			}
			val3.bounds = Bounds;
			if (Normals.Length != Vertices.Length)
			{
				val3.RecalculateNormals();
			}
			if (arms)
			{
				ArmsMesh = val3;
			}
			else
			{
				BodyMesh = val3;
			}
			Plugin.Logger.LogInfo((object)("COMPACT_MESH fps=" + arms + " vertices=" + array2.Length + " bones=" + array4.Length));
			return val3;
		}

		private int[] FilterArms(int[] triangles, bool[] armNodes)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			bool[] array = new bool[Vertices.Length];
			for (int i = 0; i < array.Length && i < Weights.Length; i++)
			{
				BoneWeight val = Weights[i];
				float num = ArmWeight(((BoneWeight)(ref val)).boneIndex0, ((BoneWeight)(ref val)).weight0, armNodes) + ArmWeight(((BoneWeight)(ref val)).boneIndex1, ((BoneWeight)(ref val)).weight1, armNodes) + ArmWeight(((BoneWeight)(ref val)).boneIndex2, ((BoneWeight)(ref val)).weight2, armNodes) + ArmWeight(((BoneWeight)(ref val)).boneIndex3, ((BoneWeight)(ref val)).weight3, armNodes);
				array[i] = num >= 0.6f;
			}
			List<int> list = new List<int>();
			for (int j = 0; j < triangles.Length; j += 3)
			{
				if (array[triangles[j]] && array[triangles[j + 1]] && array[triangles[j + 2]])
				{
					list.Add(triangles[j]);
					list.Add(triangles[j + 1]);
					list.Add(triangles[j + 2]);
				}
			}
			return list.ToArray();
		}

		private float ArmWeight(int index, float weight, bool[] nodes)
		{
			if (index < 0 || index >= Bones.Length || !nodes[Bones[index]])
			{
				return 0f;
			}
			return weight;
		}
	}
	[BepInPlugin("local.gtfo.nailong.avatar", "NAILONG Avatar Replacement", "1.4.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> AllPlayers;

		internal static ConfigEntry<bool> FirstPerson;

		internal static ConfigEntry<int> OutfitIndex;

		internal static ConfigEntry<bool> FirstPersonLilToon;

		internal static readonly ConfigEntry<float>[] OutfitScaleEntry = new ConfigEntry<float>[4];

		internal static readonly ConfigEntry<bool>[] OutfitFirstPersonEntry = new ConfigEntry<bool>[4];

		internal static readonly ConfigEntry<float>[] OutfitVerticalEntry = new ConfigEntry<float>[4];

		internal static readonly string[] OutfitFiles = new string[4] { "nailong.avatar", "naidan.avatar", "naiwa.avatar", "nai.avatar" };

		internal static readonly string[] OutfitLabels = new string[4] { "NAILONG", "NAIDAN", "NAIWA", "nai" };

		internal static readonly string[] OutfitDescriptions = new string[4] { "小奶龙", "奶蛋", "奶娃", "奶龙小可爱" };

		internal static ConfigEntry<float> Scale;

		internal static ConfigEntry<float> LobbyArmClearance;

		internal static ConfigEntry<float> WideArmLateralOffset;

		internal static ConfigEntry<float> BackwardOffset;

		internal static ConfigEntry<float> LilToonBrightness;

		internal static ConfigEntry<float> LilToonEmissionRatio;

		internal static ConfigEntry<float> LobbyBrightness;

		internal static ConfigEntry<bool> GameShader;

		internal static ConfigEntry<bool> UseLilToon;

		internal static ConfigEntry<bool> MaterialDetails;

		internal static ConfigEntry<bool> StockingDetails;

		internal static ConfigEntry<bool> SecondaryMotion;

		internal static ConfigEntry<float> MotionStrength;

		internal static string Folder;

		internal static float OutfitScale(int outfit)
		{
			if (outfit < 0 || outfit >= OutfitScaleEntry.Length || OutfitScaleEntry[outfit] == null)
			{
				return 1f;
			}
			float value = OutfitScaleEntry[outfit].Value;
			if (!(value > 0f))
			{
				return 1f;
			}
			return value;
		}

		internal static bool OutfitUsesFirstPerson(int outfit)
		{
			if (outfit < 0 || outfit >= OutfitFirstPersonEntry.Length || OutfitFirstPersonEntry[outfit] == null)
			{
				return true;
			}
			return OutfitFirstPersonEntry[outfit].Value;
		}

		internal static float OutfitVerticalOffset(int outfit)
		{
			if (outfit < 0 || outfit >= OutfitVerticalEntry.Length || OutfitVerticalEntry[outfit] == null)
			{
				return 0f;
			}
			return OutfitVerticalEntry[outfit].Value;
		}

		public override void Load()
		{
			Logger = ((BasePlugin)this).Log;
			Folder = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
			Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "启用人物模型替换。游戏中按 F7 开关。");
			AllPlayers = ((BasePlugin)this).Config.Bind<bool>("General", "ReplaceAllPlayers", true, "同时替换其他也选了这套模型的玩家。改成 false 则只替换本地玩家。");
			FirstPerson = ((BasePlugin)this).Config.Bind<bool>("General", "ReplaceFirstPersonArms", false, "替换第一人称的手臂、躯干和腿(沿用原版骨骼,不含头部)。默认关闭,游戏中按 F9 开关;开启后还需对应服装的 ReplaceFirstPerson 为 true。");
			OutfitIndex = ((BasePlugin)this).Config.Bind<int>("Outfit", "SelectedOutfit", 0, "当前使用的自定义服装:0 = NAILONG,1 = NAIDAN,2 = NAIWA,3 = nai。在衣柜里点对应卡片会自动写入。");
			FirstPersonLilToon = ((BasePlugin)this).Config.Bind<bool>("Rendering", "FirstPersonUseLilToon", false, "第一人称也使用 lilToon。默认 false,手模优先使用游戏兼容材质以降低渲染负担;第三人称仍由 UseLilToon 控制。修改后重启游戏生效。");
			float[] array = new float[4] { 1f, 0.7f, 1f, 0.4f };
			bool[] array2 = new bool[4] { true, true, true, true };
			for (int i = 0; i < OutfitFiles.Length; i++)
			{
				string text = "Outfit." + OutfitLabels[i];
				float num = ((i < array.Length) ? array[i] : 1f);
				bool flag = i < array2.Length && array2[i];
				OutfitScaleEntry[i] = ((BasePlugin)this).Config.Bind<float>(text, "ScaleMultiplier", num, "这套服装额外的缩放倍率。1 = 不额外缩放(只吃 [General] 的 BodyScaleMultiplier)。和全局倍率一样绕胯骨等比缩放,常用 0.5~0.8。");
				OutfitFirstPersonEntry[i] = ((BasePlugin)this).Config.Bind<bool>(text, "ReplaceFirstPerson", flag, "这套服装是否替换第一人称模型。关掉后第一人称保持原版手臂,模型只出现在第三人称。");
				OutfitVerticalEntry[i] = ((BasePlugin)this).Config.Bind<float>(text, "VerticalOffset", 0f, "这套服装额外的垂直偏移,单位米。正数上移、负数下沉。默认 0。");
			}
			Scale = ((BasePlugin)this).Config.Bind<float>("General", "BodyScaleMultiplier", 0.65f, "整体缩放倍率。1 = 与原版骨架腿长一致;小于 1 是绕胯骨等比缩小,脚会离地(0.8 约浮空 15 cm),常用 0.6~0.7。");
			GameShader = ((BasePlugin)this).Config.Bind<bool>("Rendering", "UseGameCharacterShader", true, "使用 GTFO 原版人物着色器,兼容游戏内光照。");
			MaterialDetails = ((BasePlugin)this).Config.Bind<bool>("Rendering", "EnhancedStockingsAndCrystals", true, "给丝袜和水晶加原版的视角相关 MatCap 高光。F6 可临时对比。");
			StockingDetails = ((BasePlugin)this).Config.Bind<bool>("Rendering", "StockingFabricSheen", true, "丝袜布料的柔光效果。F5 单独开关丝袜,不影响水晶增强。");
			UseLilToon = ((BasePlugin)this).Config.Bind<bool>("Rendering", "UseLilToon", true, "使用 Unity2019 编译的 lilToon。F6 与兼容 GTFO 材质对比。");
			LilToonBrightness = ((BasePlugin)this).Config.Bind<float>("Rendering", "LilToonBrightness", 0.3f, "反照率亮度补偿,用来抵消 GTFO 的曝光。原贴图和 alpha 通道不变。");
			LilToonEmissionRatio = ((BasePlugin)this).Config.Bind<float>("Rendering", "LilToonEmissionRatio", 0.125f, "贴图色自发光强度,相对原版 0.20 最低光照基线。0.125 = 0.025 自发光下限,0 = 关闭自发光。光照着色和场景光照探针仍然生效,实际观感取决于游戏曝光。");
			LobbyBrightness = ((BasePlugin)this).Config.Bind<float>("Rendering", "LobbyBrightness", 0.8f, "大厅预览单独的反照率补偿。大厅 UI 相机不走关卡曝光,所以用固定 0.60 光底。不会照亮关卡内的模型。");
			LobbyArmClearance = ((BasePlugin)this).Config.Bind<float>("Animation", "LobbyArmClearanceDegrees", 14f, "大厅预览时上臂外张的角度,避免手穿裙子。不改权重和骨长,关卡内瞄准不受影响。");
			WideArmLateralOffset = ((BasePlugin)this).Config.Bind<float>("Animation", "WideModelArmLateralOffsetMeters", 0.16f, "胖体型模型(NAIDAN / NAIWA)的手臂横向外移距离。奶娃躯干很宽,手臂放下会陷进身体;这里只平移自定义模型的上臂骨骼,让整条手臂悬在躯干外侧,不会旋转手臂,也不会影响原版武器/装备挂点。手臂抬起或瞄准时会自动减弱。");
			BackwardOffset = ((BasePlugin)this).Config.Bind<float>("General", "ModelBackwardOffset", 0f, "整体沿角色自身背向平移,单位米。正数把模型挪到镜头后方,负数往前。脚会跟着挪,建议 0~0.15,0 = 原对齐。");
			SecondaryMotion = ((BasePlugin)this).Config.Bind<bool>("Animation", "SecondaryMotion", true, "头发、袖子、裙摆、飘带的轻量弹簧晃动。F4 开关。不改权重、骨长和人形骨骼旋转。");
			MotionStrength = ((BasePlugin)this).Config.Bind<float>("Animation", "SecondaryMotionStrength", 1f, "弹簧晃动强度倍率(0~1.5)。角度安全上限始终生效。");
			SuteraOutfit.Initialize(((BasePlugin)this).Config);
			ClassInjector.RegisterTypeInIl2Cpp<Driver>();
			((BasePlugin)this).AddComponent<Driver>();
			((BasePlugin)this).Log.LogInfo((object)"Avatar replacement installed; visual changes are local to this client. F7 toggles, F8 captures a screenshot.");
		}
	}
	internal sealed class Rig : IDisposable
	{
		private sealed class SkinSnapshot
		{
			public SkinnedMeshRenderer Skin;

			public Mesh Mesh;

			public Transform[] Bones;

			public Transform RootBone;

			public Material[] Materials;

			public Bounds Bounds;

			public bool UpdateOffscreen;

			public bool MotionVectors;

			public ShadowCastingMode Shadows;

			public bool ReceiveShadows;

			public LightProbeUsage LightProbes;

			public ReflectionProbeUsage ReflectionProbes;

			public Transform ProbeAnchor;
		}

		private sealed class Mapping
		{
			public int Node;

			public int Human;

			public Transform Target;

			public Transform ChildTarget;

			public Quaternion TargetRest;

			public Quaternion Offset;

			public Vector3 Direction;

			public TargetPose Pose;

			public TargetPose ChildPose;
		}

		private sealed class TargetPose
		{
			public Transform Target;

			public Quaternion Rotation;

			public Vector3 Position;

			public bool NeedsPosition;

			public bool Alive;
		}

		public PlayerAgent Owner;

		public SNet_Player NetworkOwner;

		public Animator Animator;

		public bool Arms;

		public int Outfit;

		private bool loggedPlacement;

		private bool loggedArmClearance;

		public GameObject RenderRoot;

		private GameObject Root;

		private Transform[] nodes;

		private AvatarData data;

		private readonly List<Mapping> mappings = new List<Mapping>();

		private readonly List<TargetPose> targetPoses = new List<TargetPose>();

		private readonly List<GameObject> originalObjects = new List<GameObject>();

		private readonly List<Tuple<Renderer, bool>> originals = new List<Tuple<Renderer, bool>>();

		private readonly List<Renderer> visuals = new List<Renderer>();

		private readonly List<Material> ownMaterials = new List<Material>();

		private readonly List<SkinnedMeshRenderer> sheenRenderers = new List<SkinnedMeshRenderer>();

		private SkinnedMeshRenderer stockingSheen;

		private readonly List<Tuple<PlayerFaceController, bool>> nativeFaces = new List<Tuple<PlayerFaceController, bool>>();

		private readonly List<FPSRenderer> fpsRenderers = new List<FPSRenderer>();

		private readonly FpsDiscoveryBudget fpsDiscovery = new FpsDiscoveryBudget();

		private static FPSRenderer[] cachedFpsRenderers;

		private static float nextFpsSceneSearch;

		private readonly Dictionary<int, int> fpsPasses = new Dictionary<int, int>();

		private readonly Dictionary<int, RendererData[]> fpsSnapshots = new Dictionary<int, RendererData[]>();

		private float scaleMultiplier = 1f;

		private Vector3 targetScale;

		private Transform anchor;

		private Transform lightingAnchor;

		private Transform rootTransform;

		private Vector3 lastScale;

		private float maintenanceAt;

		private int mappedRootNode = -1;

		private SkinnedMeshRenderer host;

		private GameObject hostObject;

		private Mesh emptyMesh;

		private readonly List<Mesh> ownMeshes = new List<Mesh>();

		private readonly List<SkinSnapshot> skinSnapshots = new List<SkinSnapshot>();

		private readonly Dictionary<int, Mapping> mainMappings = new Dictionary<int, Mapping>();

		private SpringMotion spring;

		private static readonly Dictionary<int, int> Segments;

		public bool Valid
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Expected O, but got Unknown
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Expected O, but got Unknown
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Expected O, but got Unknown
				if (Ic.B((Object)Root) && Ic.B((Object)Animator))
				{
					return Ic.B((Object)host);
				}
				return false;
			}
		}

		public bool Installed
		{
			get
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Expected O, but got Unknown
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_0053: Expected O, but got Unknown
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Expected O, but got Unknown
				//IL_0070: Expected O, but got Unknown
				//IL_007d: 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_0092: Expected O, but got Unknown
				//IL_0092: Expected O, but got Unknown
				//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Expected O, but got Unknown
				if (!Ic.B((Object)host) || !ownMeshes.Any((Mesh m) => Ic.B((Object)m) && (Object)m == (Object)host.sharedMesh))
				{
					return false;
				}
				foreach (SkinSnapshot skinSnapshot in skinSnapshots)
				{
					if (Ic.B((Object)skinSnapshot.Skin) && (Object)skinSnapshot.Skin != (Object)host && (Object)skinSnapshot.Skin.sharedMesh != (Object)emptyMesh)
					{
						return false;
					}
				}
				if (!((Component)host).gameObject.activeInHierarchy && Ic.B((Object)RenderRoot) && RenderRoot.activeInHierarchy && skinSnapshots.Any((SkinSnapshot s) => Ic.B((Object)s.Skin) && (Object)s.Skin != (Object)host && ((Renderer)s.Skin).enabled && ((Component)s.Skin).gameObject.activeInHierarchy))
				{
					return false;
				}
				return true;
			}
		}

		public int MappingCount => mappings.Count;

		private static float NativeLegLength(Animator animator, Animator prefab, Transform hips, Transform foot)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//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_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)
			if (Ic.B((Object)prefab) && prefab.isHuman)
			{
				Transform boneTransform = prefab.GetBoneTransform((HumanBodyBones)0);
				Transform boneTransform2 = prefab.GetBoneTransform((HumanBodyBones)5);
				if (Ic.B((Object)boneTransform) && Ic.B((Object)boneTransform2))
				{
					Transform transform = ((Component)prefab).transform;
					float num = Mathf.Abs(transform.InverseTransformPoint(boneTransform.position).y - transform.InverseTransformPoint(boneTransform2.position).y);
					if (float.IsFinite(num) && num > 0.01f)
					{
						return num;
					}
				}
			}
			Transform transform2 = ((Component)animator).transform;
			float num2 = 0f;
			Transform val = foot;
			for (int i = 0; i < 16; i++)
			{
				if (!Ic.B((Object)val))
				{
					break;
				}
				if (!((Object)(object)val != (Object)(object)hips))
				{
					break;
				}
				Transform parent = val.parent;
				if (!Ic.B((Object)parent))
				{
					break;
				}
				num2 += Vector3.Distance(transform2.InverseTransformPoint(val.position), transform2.InverseTransformPoint(parent.position));
				val = parent;
			}
			if (!((Object)(object)val == (Object)(object)hips) || !float.IsFinite(num2))
			{
				return 0f;
			}
			return num2;
		}

		private Vector3 PalmDirection(int nodeIndex, Vector3 fallback)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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_01f1: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: 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_0163: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			if (data.PalmDirections.TryGetValue(nodeIndex, out var value))
			{
				return value;
			}
			Vector3 val = Vec(0f, 0f, 0f);
			float num = 0f;
			Part[] renderers = data.Renderers;
			foreach (Part part in renderers)
			{
				int num2 = Array.IndexOf(part.Bones, nodeIndex);
				if (num2 < 0 || num2 >= part.Bindposes.Length)
				{
					continue;
				}
				Surface[] surfaces = part.Surfaces;
				for (int j = 0; j < surfaces.Length; j++)
				{
					int[] triangles = surfaces[j].Triangles;
					foreach (int num3 in triangles)
					{
						if (num3 >= 0 && num3 < part.Weights.Length && num3 < part.Vertices.Length)
						{
							BoneWeight val2 = part.Weights[num3];
							float num4 = ((((BoneWeight)(ref val2)).boneIndex0 == num2) ? ((BoneWeight)(ref val2)).weight0 : 0f) + ((((BoneWeight)(ref val2)).boneIndex1 == num2) ? ((BoneWeight)(ref val2)).weight1 : 0f) + ((((BoneWeight)(ref val2)).boneIndex2 == num2) ? ((BoneWeight)(ref val2)).weight2 : 0f) + ((((BoneWeight)(ref val2)).boneIndex3 == num2) ? ((BoneWeight)(ref val2)).weight3 : 0f);
							if (!(num4 <= 0f))
							{
								val += FastPoint(part.Bindposes[num2], part.Vertices[num3]) * num4;
								num += num4;
							}
						}
					}
				}
			}
			Vector3 val3 = ((num > 0f) ? QRotate(data.Nodes[nodeIndex].WorldRotation, val * (1f / num)) : fallback);
			if (((Vector3)(ref val3)).sqrMagnitude < 1E-06f)
			{
				val3 = fallback;
			}
			data.PalmDirections[nodeIndex] = val3;
			return val3;
		}

		private static Vector3 Managed(Vector3 p)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(p.x, p.y, p.z);
		}

		private static Quaternion Managed(Quaternion q)
		{
			//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_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return new Quaternion(q.x, q.y, q.z, q.w);
		}

		private void InitializeSpring(bool[] needed)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			SpringMotion.Definition[] array = new SpringMotion.Definition[data.Nodes.Length];
			for (int i = 0; i < array.Length; i++)
			{
				Node node = data.Nodes[i];
				array[i] = new SpringMotion.Definition
				{
					Name = node.Name,
					Parent = node.Parent,
					Human = node.Human,
					LocalPosition = Managed(node.Position),
					LocalRotation = Managed(node.Rotation)
				};
			}
			spring = new SpringMotion(array, needed);
			List<SpringMotion.SkinVertex> list = new List<SpringMotion.SkinVertex>();
			Part[] renderers = data.Renderers;
			foreach (Part part in renderers)
			{
				if (!part.Skinned)
				{
					continue;
				}
				for (int k = 0; k < part.Vertices.Length; k++)
				{
					BoneWeight val = part.Weights[k];
					int num = part.Bones[((BoneWeight)(ref val)).boneIndex0];
					int num2 = part.Bones[((BoneWeight)(ref val)).boneIndex1];
					int num3 = part.Bones[((BoneWeight)(ref val)).boneIndex2];
					int num4 = part.Bones[((BoneWeight)(ref val)).boneIndex3];
					int root = -1;
					float dominant = 0f;
					float total = 0f;
					Pick(num, ((BoneWeight)(ref val)).weight0);
					Pick(num2, ((BoneWeight)(ref val)).weight1);
					Pick(num3, ((BoneWeight)(ref val)).weight2);
					Pick(num4, ((BoneWeight)(ref val)).weight3);
					if (root >= 0 && !(total < 0.5f))
					{
						list.Add(new SpringMotion.SkinVertex
						{
							Root = root,
							B0 = num,
							B1 = num2,
							B2 = num3,
							B3 = num4,
							L0 = Managed(FastPoint(part.Bindposes[((BoneWeight)(ref val)).boneIndex0], part.Vertices[k])),
							L1 = Managed(FastPoint(part.Bindposes[((BoneWeight)(ref val)).boneIndex1], part.Vertices[k])),
							L2 = Managed(FastPoint(part.Bindposes[((BoneWeight)(ref val)).boneIndex2], part.Vertices[k])),
							L3 = Managed(FastPoint(part.Bindposes[((BoneWeight)(ref val)).boneIndex3], part.Vertices[k])),
							Weights = new Vector4(((BoneWeight)(ref val)).weight0, ((BoneWeight)(ref val)).weight1, ((BoneWeight)(ref val)).weight2, ((BoneWeight)(ref val)).weight3)
						});
					}
					void Pick(int bone, float weight)
					{
						int num5 = spring.ClothRoot(bone);
						if (num5 >= 0)
						{
							total += weight;
							if (weight > dominant)
							{
								dominant = weight;
								root = num5;
							}
						}
					}
				}
			}
			spring.ConfigureCloth(list.ToArray());
			Plugin.Logger.LogDebug((object)("SUTERA_SPRINGS joints=" + spring.Count + " hair=" + spring.HairCount + " skirt=" + spring.SkirtCount + " sleeves=" + spring.SleeveCount + " ribbons=" + spring.RibbonCount + " cloth_probes=" + spring.ProbeCount + " fps=" + Arms));
		}

		private static IEnumerable<FPSRenderer> AllFPS()
		{
			foreach (FPSRenderer item in Object.FindObjectsOfType<FPSRenderer>())
			{
				int num;
				if (Ic.B((Object)item))
				{
					Scene scene = ((Component)item).gameObject.scene;
					num = (((Scene)(ref scene)).IsValid() ? 1 : 0);
				}
				else
				{
					num = 0;
				}
				if (num != 0)
				{
					yield return item;
				}
			}
		}

		public Rig(AvatarData avatar, PlayerAgent owner, Animator animator, bool arms, GameObject renderRoot, int outfit)
		{
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f7: Expected O, but got Unknown
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fb: Expected O, but got Unknown
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_0512: Expected O, but got Unknown
			//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Unknown result type (might be due to invalid IL or missing references)
			//IL_069e: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a8: Expected O, but got Unknown
			//IL_076d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0777: Expected O, but got Unknown
			//IL_088c: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ae: Expected O, but got Unknown
			//IL_08e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ee: Expected O, but got Unknown
			//IL_07b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_07c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_07d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_07dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_07eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0804: Unknown result type (might be due to invalid IL or missing references)
			//IL_0823: Unknown result type (might be due to invalid IL or missing references)
			//IL_082a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0831: Unknown result type (might be due to invalid IL or missing references)
			//IL_0838: Unknown result type (might be due to invalid IL or missing references)
			//IL_090b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0915: Expected O, but got Unknown
			//IL_0bdd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0920: Unknown result type (might be due to invalid IL or missing references)
			//IL_092a: Expected O, but got Unknown
			//IL_0917: Unknown result type (might be due to invalid IL or missing references)
			//IL_0951: Unknown result type (might be due to invalid IL or missing references)
			//IL_095a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0964: Expected O, but got Unknown
			//IL_0bf0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c01: Expected I4, but got Unknown
			//IL_093b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0940: Unknown result type (might be due to invalid IL or missing references)
			//IL_0947: Unknown result type (might be due to invalid IL or missing references)
			//IL_094c: Unknown result type (might be due to invalid IL or missing references)
			//IL_09bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c9: Expected O, but got Unknown
			//IL_097e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0988: Expected O, but got Unknown
			//IL_09ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f8: Expected O, but got Unknown
			//IL_09a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ad: Expected O, but got Unknown
			//IL_0c37: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c66: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c6b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c81: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c83: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c88: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a95: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a9f: Expected O, but got Unknown
			//IL_0a28: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a32: Expected O, but got Unknown
			//IL_0b1e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b20: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac7: Expected O, but got Unknown
			//IL_0a3a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a44: Expected O, but got Unknown
			//IL_0aec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0acf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ad4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ae5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d9d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0da7: Expected O, but got Unknown
			//IL_0dad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0db7: Expected O, but got Unknown
			//IL_0dce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e00: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e1b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e2c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e31: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e42: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a79: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a83: Expected O, but got Unknown
			//IL_0ead: Unknown result type (might be due to invalid IL or missing references)
			//IL_0eb7: Expected O, but got Unknown
			//IL_103f: Unknown result type (might be due to invalid IL or missing references)
			//IL_1044: Unknown result type (might be due to invalid IL or missing references)
			//IL_105c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1061: Unknown result type (might be due to invalid IL or missing references)
			//IL_1066: Unknown result type (might be due to invalid IL or missing references)
			//IL_10b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_10b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_10d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_10e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_10ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_10f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_10f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_116c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1176: Expected O, but got Unknown
			//IL_1208: Unknown result type (might be due to invalid IL or missing references)
			//IL_120f: Expected O, but got Unknown
			//IL_125e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1273: Unknown result type (might be due to invalid IL or missing references)
			//IL_1288: Unknown result type (might be due to invalid IL or missing references)
			//IL_13be: Unknown result type (might be due to invalid IL or missing references)
			//IL_13c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_13d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_13ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_13f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_14a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_14ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_1501: Unknown result type (might be due to invalid IL or missing references)
			//IL_150b: Expected O, but got Unknown
			//IL_153e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1548: Expected O, but got Unknown
			//IL_15ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_15b8: Expected O, but got Unknown
			//IL_15c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_15d0: Expected O, but got Unknown
			//IL_1647: Unknown result type (might be due to invalid IL or missing references)
			//IL_164c: Unknown result type (might be due to invalid IL or missing references)
			//IL_166e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1673: Unknown result type (might be due to invalid IL or missing references)
			//IL_1688: Unknown result type (might be due to invalid IL or missing references)
			//IL_168d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1695: Unknown result type (might be due to invalid IL or missing references)
			//IL_169a: Unknown result type (might be due to invalid IL or missing references)
			//IL_171d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1727: Expected O, but got Unknown
			//IL_19cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_19d6: Expected O, but got Unknown
			//IL_175b: Unknown result type (might be due to invalid IL or missing references)
			//IL_176e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1773: Unknown result type (might be due to invalid IL or missing references)
			//IL_1778: Unknown result type (might be due to invalid IL or missing references)
			//IL_179a: Unknown result type (might be due to invalid IL or missing references)
			//IL_179f: Unknown result type (might be due to invalid IL or missing references)
			//IL_17ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_17b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b33: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b3e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b48: Expected O, but got Unknown
			//IL_1b48: Expected O, but got Unknown
			//IL_17bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_17c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_17c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_17cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a5c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a8e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1a98: Expected O, but got Unknown
			//IL_17e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_17ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_17f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_17f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b8c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1b9d: Expected O, but got Unknown
			//IL_1bb2: Unknown result type (might be due to invalid IL or missing references)
			//IL_1bbc: Expected O, but got Unknown
			//IL_18e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_18f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_1920: Unknown result type (might be due to invalid IL or missing references)
			//IL_1927: Expected O, but got Unknown
			//IL_193d: Unknown result type (might be due to invalid IL or missing references)
			//IL_1947: Expected O, but got Unknown
			//IL_1c4b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1c5c: Expected O, but got Unknown
			//IL_1c9c: Unknown result type (might be due to invalid IL or missing references)
			//IL_1ca6: Expected O, but got Unknown
			//IL_1caf: Unknown result type (might be due to invalid IL or missing references)
			//IL_1cba: Unknown result type (might be due to invalid IL or missing references)
			//IL_1cc4: Expected O, but got Unknown
			//IL_1cc4: Expected O, but got Unknown
			//IL_1d45: Unknown result type (might be due to invalid IL or missing references)
			//IL_1d4f: Expected O, but got Unknown
			//IL_1f9b: Unknown result type (might be due to invalid IL or missing references)
			//IL_1fa0: Unknown result type (might be due to invalid IL or missing references)
			//IL_1fa5: Unknown result type (might be due to invalid IL or missing references)
			//IL_1e2e: Unknown result type (might be due to invalid IL or missing references)
			//IL_1e38: Expected O, but got Unknown
			Outfit = outfit;
			Rig rig = this;
			Stopwatch stopwatch = Stopwatch.StartNew();
			data = avatar;
			Owner = owner;
			Animator = animator;
			Arms = arms;
			RenderRoot = renderRoot;
			try
			{
				anchor = ((Component)animator).transform;
				SkinnedMeshRenderer[] array = ((IEnumerable<SkinnedMeshRenderer>)(Ic.B((Object)renderRoot) ? renderRoot.GetComponentsInChildren<SkinnedMeshRenderer>(true) : ((Component)animator).GetComponentsInChildren<SkinnedMeshRenderer>(true))).ToArray();
				if (array.Length == 0)
				{
					array = ((IEnumerable<SkinnedMeshRenderer>)((Component)animator).GetComponentsInChildren<SkinnedMeshRenderer>(true)).ToArray();
				}
				Transform[] array2 = (from b in array.Where((SkinnedMeshRenderer s) => ((Renderer)s).enabled && ((Component)s).gameObject.activeInHierarchy).SelectMany((SkinnedMeshRenderer s) => ((IEnumerable<Transform>)s.bones).ToArray())
					where Ic.B((Object)b)
					group b by ((Object)b).GetInstanceID() into g
					select g.First()).ToArray();
				Animator val = null;
				foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<Animator>()))
				{
					Animator val2 = ((Il2CppObjectBase)item).TryCast<Animator>();
					if (!Ic.B((Object)val2) || !val2.isHuman)
					{
						continue;
					}
					Scene scene = ((Component)val2).gameObject.scene;
					if (!((Scene)(ref scene)).IsValid())
					{
						if (((Object)val2).name == ((Object)animator).name.Replace("(Clone)", ""))
						{
							val = val2;
							break;
						}
						if (((Object)val2).name == "PlayerCharacter_rig")
						{
							val = val2;
						}
					}
				}
				Plugin.Logger.LogDebug((object)("BIND_BASELINE arms=" + arms + " name=" + (Ic.B((Object)val) ? ((Object)val).name : "legacy animator")));
				Plugin.Logger.LogDebug((object)("ACTIVE_BONE_SET arms=" + arms + " count=" + array2.Length + " names=" + string.Join(",", from b in array2.Take(65)
					select ((Object)b).name)));
				Material template = (from s in array
					where ((Renderer)s).enabled && ((Component)s).gameObject.activeInHierarchy && Ic.B((Object)((Renderer)s).sharedMaterial) && Ic.B((Object)((Renderer)s).sharedMaterial.shader)
					select ((Renderer)s).sharedMaterial).FirstOrDefault();
				if (!Ic.B((Object)template))
				{
					template = (from s in array
						where Ic.B((Object)((Renderer)s).sharedMaterial) && Ic.B((Object)((Renderer)s).sharedMaterial.shader)
						select ((Renderer)s).sharedMaterial).FirstOrDefault();
				}
				SkinnedMeshRenderer[] array3 = array;
				foreach (SkinnedMeshRenderer val3 in array3)
				{
					Plugin.Logger.LogDebug((object)("ORIGINAL_SKIN arms=" + arms + " name=" + ((Object)val3).name + " active=" + ((Component)val3).gameObject.activeInHierarchy + " enabled=" + ((Renderer)val3).enabled + " layer=" + ((Component)val3).gameObject.layer + " shader=" + (Ic.B((Object)((Renderer)val3).sharedMaterial) ? ((Object)((Renderer)val3).sharedMaterial.shader).name : "null")));
				}
				ManualLogSource logger = Plugin.Logger;
				string[] arr