Decompiled source of XMC VillagerCharacter v1.0.3

BepInEx/plugins/XMC.VillagerCharacter/XMC.VillagerCharacter.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using CellMenu;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using Player;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("XMC.VillagerCharacter")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("XMC.VillagerCharacter")]
[assembly: AssemblyTitle("XMC.VillagerCharacter")]
[assembly: AssemblyVersion("1.0.3.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace Xmc.VillagerCharacter
{
	public sealed class CharacterDriver : MonoBehaviour
	{
		private readonly Dictionary<int, VillagerRig> rigs = new Dictionary<int, VillagerRig>();

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

		private ModelData? model;

		private Texture2D? texture;

		private float nextScan;

		public CharacterDriver(IntPtr pointer)
			: base(pointer)
		{
		}

		public void Start()
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			try
			{
				model = ModelData.Read(Path.Combine(Plugin.AssetFolder, "villager_model.json"));
				string text = Path.Combine(Plugin.AssetFolder, model.Texture);
				if (new FileInfo(text).Length > 4194304)
				{
					throw new InvalidDataException("人物贴图超过 4 MB");
				}
				byte[] array = File.ReadAllBytes(text);
				if (array.Length < 24 || !array.Take(8).SequenceEqual(new byte[8] { 137, 80, 78, 71, 13, 10, 26, 10 }))
				{
					throw new InvalidDataException("人物贴图不是有效 PNG");
				}
				uint num = ReadBigEndian(array, 16);
				uint num2 = ReadBigEndian(array, 20);
				bool flag = ((num < 1 || num > 2048) ? true : false);
				bool flag2 = flag;
				if (!flag2)
				{
					bool flag3 = ((num2 < 1 || num2 > 2048) ? true : false);
					flag2 = flag3;
				}
				if (flag2)
				{
					throw new InvalidDataException("人物贴图尺寸超过限制");
				}
				texture = new Texture2D(2, 2, (TextureFormat)4, false);
				if (!ImageConversion.LoadImage(texture, Il2CppStructArray<byte>.op_Implicit(array), false))
				{
					throw new InvalidDataException("人物贴图解码失败");
				}
				((Object)texture).name = "XMC_Villager_PixelAtlas";
				((Texture)texture).filterMode = (FilterMode)0;
				((Texture)texture).wrapMode = (TextureWrapMode)1;
			}
			catch (Exception ex)
			{
				model = null;
				Plugin.Logger.LogError((object)("人物皮肤未启用,原人物保持不变:" + ex));
			}
		}

		private static uint ReadBigEndian(byte[] bytes, int offset)
		{
			return (uint)((bytes[offset] << 24) | (bytes[offset + 1] << 16) | (bytes[offset + 2] << 8) | bytes[offset + 3]);
		}

		public void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.Toggle.Value))
			{
				Plugin.Enabled.Value = !Plugin.Enabled.Value;
				nextScan = 0f;
				Plugin.Logger.LogInfo((object)(Plugin.Enabled.Value ? "方块村民外观已开启" : "方块村民外观已关闭,恢复原人物"));
			}
			if (!Plugin.Enabled.Value && rigs.Count > 0)
			{
				Clear();
			}
		}

		public void LateUpdate()
		{
			if (!Plugin.Enabled.Value || model == null || (Object)(object)texture == (Object)null)
			{
				return;
			}
			if (Time.unscaledTime >= nextScan)
			{
				nextScan = Time.unscaledTime + 1f;
				try
				{
					Scan();
				}
				catch (Exception ex)
				{
					Plugin.Logger.LogWarning((object)("人物扫描失败,稍后重试:" + ex.Message));
				}
			}
			foreach (VillagerRig value in rigs.Values)
			{
				value.HideOriginals();
			}
		}

		private void Scan()
		{
			HashSet<int> hashSet = new HashSet<int>();
			string[] array = Plugin.Slots.Value.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				if (int.TryParse(array[i].Trim(), out var result) && result >= 0 && result <= 3)
				{
					hashSet.Add(result);
				}
			}
			HashSet<int> alive = new HashSet<int>();
			foreach (int item in hashSet)
			{
				PlayerManager current2 = PlayerManager.Current;
				PlayerAgent val = ((current2 != null) ? current2.GetPlayerAgentInSlot(item) : null);
				if ((Object)(object)val == (Object)null || val.IsBeingDestroyed || val.IsBeingDespawned || !((Component)val).gameObject.activeInHierarchy)
				{
					continue;
				}
				PlayerAgent localPlayerAgent = PlayerManager.GetLocalPlayerAgent();
				if (!Plugin.IncludeLocal.Value && (Object)(object)localPlayerAgent != (Object)null && ((Object)localPlayerAgent).GetInstanceID() == ((Object)val).GetInstanceID())
				{
					continue;
				}
				int instanceID = ((Object)val).GetInstanceID();
				alive.Add(instanceID);
				if (rigs.TryGetValue(instanceID, out VillagerRig value))
				{
					if (value.Valid(val))
					{
						continue;
					}
					value.Dispose();
					rigs.Remove(instanceID);
				}
				if (!retryAt.TryGetValue(instanceID, out var value2) || !(Time.unscaledTime < value2))
				{
					VillagerRig villagerRig = null;
					try
					{
						villagerRig = new VillagerRig(val, model, texture);
						rigs.Add(instanceID, villagerRig);
						retryAt.Remove(instanceID);
						Plugin.Logger.LogInfo((object)("村民外观已挂载:槽位 " + item + " / " + val.PlayerName + " / " + villagerRig.Parts + " 个骨骼分组"));
					}
					catch (Exception ex)
					{
						villagerRig?.Dispose();
						retryAt[instanceID] = Time.unscaledTime + 15f;
						Plugin.Logger.LogWarning((object)("槽位 " + item + " 保留原人物,未替换:" + ex.Message));
					}
				}
			}
			int[] array2 = rigs.Keys.Where((int id) => !alive.Contains(id)).ToArray();
			foreach (int key in array2)
			{
				rigs[key].Dispose();
				rigs.Remove(key);
			}
			array2 = retryAt.Keys.Where((int id) => !alive.Contains(id)).ToArray();
			foreach (int key2 in array2)
			{
				retryAt.Remove(key2);
			}
		}

		private void Clear()
		{
			foreach (VillagerRig value in rigs.Values)
			{
				value.Dispose();
			}
			rigs.Clear();
			retryAt.Clear();
		}

		public void OnDestroy()
		{
			Clear();
			if ((Object)(object)texture != (Object)null)
			{
				Object.Destroy((Object)(object)texture);
			}
		}
	}
	internal sealed class LobbyVillagerRig : IDisposable
	{
		private readonly List<GameObject> objects = new List<GameObject>();

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

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

		private readonly Material material;

		private bool disposed;

		internal LobbyVillagerRig(CM_PlayerLobbyBar bar, ModelData model, Texture2D texture)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0307: Expected O, but got Unknown
			Animator val = bar.m_playerAnim ?? throw new InvalidOperationException("大厅人物动画未生成");
			SkinnedMeshRenderer[] array = ((IEnumerable<SkinnedMeshRenderer>)bar.m_playerModelRenderers)?.Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer != (Object)null && (Object)(object)renderer.sharedMesh != (Object)null).ToArray() ?? Array.Empty<SkinnedMeshRenderer>();
			if (array.Length == 0)
			{
				throw new InvalidOperationException("大厅人物蒙皮网格未生成");
			}
			try
			{
				Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal);
				foreach (string boneName in ModelData.BoneNames)
				{
					Transform val2 = null;
					if (val.isHuman && Enum.TryParse<HumanBodyBones>(boneName, out HumanBodyBones result))
					{
						val2 = val.GetBoneTransform(result);
					}
					if ((Object)(object)val2 == (Object)null)
					{
						val2 = FindBone(((Component)val).transform, boneName);
					}
					if ((Object)(object)val2 == (Object)null)
					{
						throw new InvalidOperationException("大厅人物缺少骨骼 " + boneName);
					}
					dictionary.Add(boneName, val2);
				}
				Transform root = bar.m_playerModelAlign ?? ((Component)val).transform;
				Vector3 val3 = root.InverseTransformPoint(dictionary["Head"].position);
				Vector3 val4 = root.InverseTransformPoint(dictionary["LeftFoot"].position);
				float scale = Mathf.Abs(val3.y - val4.y) / (model.SourceHeadHeight - model.SourceFootHeight);
				if (!float.IsFinite(scale) || scale < 0.25f || scale > 3f)
				{
					throw new InvalidOperationException("大厅人物比例异常");
				}
				material = CreateMaterial(texture);
				foreach (ModelPart part in model.Parts)
				{
					Transform bone = dictionary[part.Bone];
					Vector3[] array2 = part.Vertices.Select((float[] vertex) => bone.InverseTransformPoint(root.TransformPoint(new Vector3(vertex[0], vertex[1], vertex[2]) * scale))).ToArray();
					Mesh val5 = new Mesh
					{
						name = "XMC_LobbyVillager_" + part.Name
					};
					val5.vertices = Il2CppStructArray<Vector3>.op_Implicit(array2);
					val5.uv = Il2CppStructArray<Vector2>.op_Implicit(((IEnumerable<float[]>)part.UV).Select((Func<float[], Vector2>)((float[] uv) => new Vector2(uv[0], uv[1]))).ToArray());
					val5.triangles = Il2CppStructArray<int>.op_Implicit(part.Triangles.ToArray());
					val5.RecalculateNormals();
					val5.RecalculateBounds();
					meshes.Add(val5);
					GameObject val6 = new GameObject("XMC_LobbyVillager_" + part.Name)
					{
						layer = ((Component)array[0]).gameObject.layer
					};
					val6.transform.SetParent(bone, false);
					val6.AddComponent<MeshFilter>().sharedMesh = val5;
					((Renderer)val6.AddComponent<MeshRenderer>()).sharedMaterial = material;
					objects.Add(val6);
				}
				SkinnedMeshRenderer[] array3 = array;
				foreach (SkinnedMeshRenderer val7 in array3)
				{
					originals.Add(((Renderer)(object)val7, ((Renderer)val7).enabled));
					((Renderer)val7).enabled = false;
				}
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		private static Transform? FindBone(Transform root, string name)
		{
			string text = name.ToLowerInvariant();
			foreach (Transform componentsInChild in ((Component)root).GetComponentsInChildren<Transform>(true))
			{
				string text2 = new string(((Object)componentsInChild).name.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray());
				if (text2 == text || text2.EndsWith("bip01" + text, StringComparison.Ordinal) || text2.EndsWith("mixamorig" + text, StringComparison.Ordinal))
				{
					return componentsInChild;
				}
			}
			return null;
		}

		private static Material CreateMaterial(Texture2D texture)
		{
			//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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[3] { "Standard", "Legacy Shaders/Diffuse", "Unlit/Texture" };
			for (int i = 0; i < array.Length; i++)
			{
				Shader val = Shader.Find(array[i]);
				if (!((Object)(object)val == (Object)null) && val.isSupported)
				{
					Material val2 = new Material(val)
					{
						name = "XMC_LobbyVillager_PixelCloth",
						mainTexture = (Texture)(object)texture
					};
					if (val2.HasProperty("_Color"))
					{
						val2.SetColor("_Color", Color.white);
					}
					if (val2.HasProperty("_Glossiness"))
					{
						val2.SetFloat("_Glossiness", 0f);
					}
					if (val2.HasProperty("_Metallic"))
					{
						val2.SetFloat("_Metallic", 0f);
					}
					return val2;
				}
			}
			throw new InvalidOperationException("大厅没有可用人物材质");
		}

		internal void HideOriginals()
		{
			if (disposed)
			{
				return;
			}
			foreach (var original in originals)
			{
				if ((Object)(object)original.Renderer != (Object)null)
				{
					original.Renderer.enabled = false;
				}
			}
		}

		public void Dispose()
		{
			if (disposed)
			{
				return;
			}
			disposed = true;
			foreach (var original in originals)
			{
				if ((Object)(object)original.Renderer != (Object)null)
				{
					original.Renderer.enabled = original.Enabled;
				}
			}
			foreach (GameObject @object in objects)
			{
				if ((Object)(object)@object != (Object)null)
				{
					Object.Destroy((Object)(object)@object);
				}
			}
			foreach (Mesh mesh in meshes)
			{
				if ((Object)(object)mesh != (Object)null)
				{
					Object.Destroy((Object)(object)mesh);
				}
			}
			if ((Object)(object)material != (Object)null)
			{
				Object.Destroy((Object)(object)material);
			}
			objects.Clear();
			meshes.Clear();
			originals.Clear();
		}
	}
	public sealed class ModelData
	{
		public static readonly HashSet<string> BoneNames = new HashSet<string>(StringComparer.Ordinal)
		{
			"Head", "Chest", "Hips", "LeftUpperLeg", "LeftLowerLeg", "LeftFoot", "RightUpperLeg", "RightLowerLeg", "RightFoot", "LeftUpperArm",
			"LeftLowerArm", "LeftHand", "RightUpperArm", "RightLowerArm", "RightHand"
		};

		public int Version { get; set; }

		public string Name { get; set; } = string.Empty;

		public string Texture { get; set; } = string.Empty;

		public float SourceHeadHeight { get; set; }

		public float SourceFootHeight { get; set; }

		public List<ModelPart> Parts { get; set; } = new List<ModelPart>();

		public static ModelData Read(string path)
		{
			if (new FileInfo(path).Length > 2097152)
			{
				throw new InvalidDataException("人物模型配置过大");
			}
			ModelData? obj = JsonSerializer.Deserialize<ModelData>(File.ReadAllText(path)) ?? throw new InvalidDataException("人物模型为空");
			obj.Validate();
			return obj;
		}

		public void Validate()
		{
			bool flag = Version != 1 || Parts == null;
			if (!flag)
			{
				int count = Parts.Count;
				bool flag2 = ((count < 1 || count > 64) ? true : false);
				flag = flag2;
			}
			if (flag)
			{
				throw new InvalidDataException("人物模型版本或分组数量无效");
			}
			if (!float.IsFinite(SourceHeadHeight) || !float.IsFinite(SourceFootHeight) || SourceHeadHeight - SourceFootHeight < 0.5f)
			{
				throw new InvalidDataException("人物参考身高无效");
			}
			if (string.IsNullOrWhiteSpace(Texture) || Texture.Contains('/') || Texture.Contains('\\') || Texture.Contains(':') || !Texture.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
			{
				throw new InvalidDataException("贴图必须是模型目录内的 PNG 文件");
			}
			HashSet<string> bones = new HashSet<string>(StringComparer.Ordinal);
			foreach (ModelPart part in Parts)
			{
				if (part == null || string.IsNullOrWhiteSpace(part.Name) || !BoneNames.Contains(part.Bone) || !bones.Add(part.Bone))
				{
					throw new InvalidDataException("人物骨骼名称重复或无效");
				}
				if (part.Anchor == null || part.Anchor.Length != 3 || part.Anchor.Any((float value) => !float.IsFinite(value) || Math.Abs(value) > 4f))
				{
					throw new InvalidDataException("人物分组锚点无效");
				}
				if (!float.IsFinite(part.Length) || part.Length < 0f || part.Length > 2f || part.EndBone == null || (part.EndBone.Length > 0 && (!BoneNames.Contains(part.EndBone) || part.Length <= 0f)))
				{
					throw new InvalidDataException("人物肢体参考长度无效");
				}
				flag = part.Vertices == null || part.UV == null || part.Triangles == null;
				if (!flag)
				{
					int count = part.Vertices.Count;
					bool flag3 = ((count < 3 || count > 10000) ? true : false);
					flag = flag3;
				}
				bool flag2 = flag || part.UV.Count != part.Vertices.Count;
				if (!flag2)
				{
					int count = part.Triangles.Count;
					bool flag3 = ((count < 3 || count > 60000) ? true : false);
					flag2 = flag3;
				}
				if (flag2 || part.Triangles.Count % 3 != 0)
				{
					throw new InvalidDataException("人物网格数量无效");
				}
				if (part.Vertices.Any((float[] vertex) => vertex == null || vertex.Length != 3 || vertex.Any((float value) => !float.IsFinite(value) || Math.Abs(value) > 4f)))
				{
					throw new InvalidDataException("人物顶点无效");
				}
				if (part.UV.Any((float[] uv) => uv == null || uv.Length != 2 || uv.Any((float value) => !float.IsFinite(value) || value < 0f || value > 1f)))
				{
					throw new InvalidDataException("人物 UV 无效");
				}
				if (part.Triangles.Any((int index) => index < 0 || index >= part.Vertices.Count))
				{
					throw new InvalidDataException("人物三角形索引越界");
				}
			}
			if (BoneNames.Any((string bone) => !bones.Contains(bone)))
			{
				throw new InvalidDataException("人物必须包含完整的头、身体和四肢");
			}
		}
	}
	public sealed class ModelPart
	{
		public string Name { get; set; } = string.Empty;

		public string Bone { get; set; } = string.Empty;

		public float[] Anchor { get; set; } = Array.Empty<float>();

		public string EndBone { get; set; } = string.Empty;

		public float Length { get; set; }

		public List<float[]> Vertices { get; set; } = new List<float[]>();

		public List<float[]> UV { get; set; } = new List<float[]>();

		public List<int> Triangles { get; set; } = new List<int>();
	}
	[BepInPlugin("xmc.gtfo.villager_character", "XMC Brown Robe Villager", "1.0.3")]
	public sealed class Plugin : BasePlugin
	{
		internal static ManualLogSource Logger = null;

		internal static ConfigEntry<bool> Enabled = null;

		internal static ConfigEntry<bool> IncludeLocal = null;

		internal static ConfigEntry<string> Slots = null;

		internal static ConfigEntry<KeyCode> Toggle = null;

		internal static string AssetFolder = string.Empty;

		public override void Load()
		{
			Logger = ((BasePlugin)this).Log;
			AssetFolder = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "Assets");
			Enabled = ((BasePlugin)this).Config.Bind<bool>("Appearance", "Enabled", true, "开启方块村民人物外观,仅改变本机显示。");
			IncludeLocal = ((BasePlugin)this).Config.Bind<bool>("Appearance", "IncludeLocalPlayer", false, "是否替换本机玩家身体;关闭后只替换其他玩家,不处理大厅预览。");
			Slots = ((BasePlugin)this).Config.Bind<string>("Appearance", "PlayerSlots", "0,1,2,3", "需要替换的玩家槽位,从 0 开始,逗号分隔;默认覆盖本机看到的全部队友和机器人。");
			Toggle = ((BasePlugin)this).Config.Bind<KeyCode>("Hotkeys", "Toggle", (KeyCode)287, "切换人物外观;关闭后恢复原身体渲染。");
			ClassInjector.RegisterTypeInIl2Cpp<CharacterDriver>();
			((BasePlugin)this).AddComponent<CharacterDriver>();
			((BasePlugin)this).Log.LogInfo((object)"棕袍方块村民 1.0.3 已载入:F6 开关;只替换任务内其他玩家,不处理本机和大厅预览。");
		}
	}
	internal sealed class VillagerRig : IDisposable
	{
		private readonly Animator animator;

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

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

		private readonly Dictionary<int, (Renderer Renderer, bool Enabled)> originals = new Dictionary<int, (Renderer, bool)>();

		private Material? material;

		private bool disposed;

		internal int Parts => objects.Count;

		internal VillagerRig(PlayerAgent player, ModelData model, Texture2D texture)
		{
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0347: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0372: Unknown result type (might be due to invalid IL or missing references)
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			//IL_0419: Unknown result type (might be due to invalid IL or missing references)
			//IL_041e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0429: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0437: Unknown result type (might be due to invalid IL or missing references)
			//IL_043c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0524: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_054e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0567: Expected O, but got Unknown
			//IL_047b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0480: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_0489: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_0496: Unknown result type (might be due to invalid IL or missing references)
			//IL_049b: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_060f: Expected O, but got Unknown
			//IL_0500: Unknown result type (might be due to invalid IL or missing references)
			//IL_0507: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			animator = player.AnimatorBody ?? throw new InvalidOperationException("第三人称动画骨架尚未生成");
			try
			{
				SkinnedMeshRenderer[] array = ((IEnumerable<SkinnedMeshRenderer>)((Component)animator).GetComponentsInChildren<SkinnedMeshRenderer>(true)).Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer != (Object)null && (Object)(object)renderer.sharedMesh != (Object)null && !((Object)renderer).name.StartsWith("XMC_", StringComparison.Ordinal)).ToArray();
				if (array.Length == 0 && (Object)(object)player.m_rigBaseForClothes != (Object)null)
				{
					array = ((IEnumerable<SkinnedMeshRenderer>)player.m_rigBaseForClothes.GetComponentsInChildren<SkinnedMeshRenderer>(true)).Where((SkinnedMeshRenderer renderer) => (Object)(object)renderer != (Object)null && (Object)(object)renderer.sharedMesh != (Object)null).ToArray();
				}
				if (array.Length == 0)
				{
					throw new InvalidOperationException("未找到原身体蒙皮网格");
				}
				Dictionary<string, Transform> dictionary = new Dictionary<string, Transform>(StringComparer.Ordinal);
				foreach (string boneName in ModelData.BoneNames)
				{
					Transform val = null;
					if (animator.isHuman && Enum.TryParse<HumanBodyBones>(boneName, out HumanBodyBones result))
					{
						val = animator.GetBoneTransform(result);
					}
					if ((Object)(object)val == (Object)null && boneName == "Chest" && animator.isHuman)
					{
						val = animator.GetBoneTransform((HumanBodyBones)7);
					}
					if ((Object)(object)val == (Object)null)
					{
						val = FindBone(((Component)animator).transform, boneName);
					}
					if ((Object)(object)val == (Object)null)
					{
						throw new InvalidOperationException("缺少骨骼 " + boneName + ";不隐藏原人物");
					}
					dictionary.Add(boneName, val);
				}
				Dictionary<int, Matrix4x4> dictionary2 = new Dictionary<int, Matrix4x4>();
				Matrix4x4 val2;
				foreach (SkinnedMeshRenderer item in array.OrderByDescending((SkinnedMeshRenderer renderer) => renderer.sharedMesh.vertexCount))
				{
					Il2CppStructArray<Matrix4x4> bindposes = item.sharedMesh.bindposes;
					Il2CppReferenceArray<Transform> bones = item.bones;
					if (((Il2CppArrayBase<Transform>)(object)bones).Length != ((Il2CppArrayBase<Matrix4x4>)(object)bindposes).Length)
					{
						continue;
					}
					for (int num = 0; num < ((Il2CppArrayBase<Transform>)(object)bones).Length; num++)
					{
						if ((Object)(object)((Il2CppArrayBase<Transform>)(object)bones)[num] != (Object)null && !dictionary2.ContainsKey(((Object)((Il2CppArrayBase<Transform>)(object)bones)[num]).GetInstanceID()))
						{
							int instanceID = ((Object)((Il2CppArrayBase<Transform>)(object)bones)[num]).GetInstanceID();
							Matrix4x4 localToWorldMatrix = ((Component)item).transform.localToWorldMatrix;
							val2 = ((Il2CppArrayBase<Matrix4x4>)(object)bindposes)[num];
							dictionary2.Add(instanceID, localToWorldMatrix * ((Matrix4x4)(ref val2)).inverse);
						}
					}
				}
				foreach (KeyValuePair<string, Transform> item2 in dictionary)
				{
					if (!dictionary2.ContainsKey(((Object)item2.Value).GetInstanceID()))
					{
						throw new InvalidOperationException("原蒙皮缺少 " + item2.Key + " 的绑定姿态;不使用当前动画姿态猜测");
					}
				}
				Matrix4x4 root = ((Component)player).transform.localToWorldMatrix;
				Matrix4x4 inverse = ((Matrix4x4)(ref root)).inverse;
				val2 = dictionary2[((Object)dictionary["Head"]).GetInstanceID()];
				Vector3 val3 = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(((Matrix4x4)(ref val2)).MultiplyPoint3x4(Vector3.zero));
				val2 = dictionary2[((Object)dictionary["LeftFoot"]).GetInstanceID()];
				Vector3 val4 = ((Matrix4x4)(ref inverse)).MultiplyPoint3x4(((Matrix4x4)(ref val2)).MultiplyPoint3x4(Vector3.zero));
				float num2 = Mathf.Abs(val3.y - val4.y) / (model.SourceHeadHeight - model.SourceFootHeight);
				if (!float.IsFinite(num2) || num2 < 0.35f || num2 > 2f)
				{
					throw new InvalidOperationException("人物骨架比例异常");
				}
				material = CreateMaterial(texture, array);
				foreach (ModelPart part in model.Parts)
				{
					Transform val5 = dictionary[part.Bone];
					Matrix4x4 val6 = dictionary2[((Object)val5).GetInstanceID()];
					Matrix4x4 inverseBone = ((Matrix4x4)(ref val6)).inverse;
					Vector3 start = ((Matrix4x4)(ref val6)).MultiplyPoint3x4(Vector3.zero);
					Quaternion rotation = Quaternion.identity;
					float partScale = num2;
					if (part.EndBone.Length > 0)
					{
						val2 = dictionary2[((Object)dictionary[part.EndBone]).GetInstanceID()];
						Vector3 val7 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(Vector3.zero);
						Vector3 val8 = ((Matrix4x4)(ref inverse)).MultiplyVector(val7 - start);
						partScale = ((Vector3)(ref val8)).magnitude / part.Length;
						if (!float.IsFinite(partScale) || partScale < 0.2f || partScale > 3f)
						{
							throw new InvalidOperationException("肢体比例异常:" + part.Bone);
						}
						rotation = Quaternion.FromToRotation(Vector3.down, ((Vector3)(ref val8)).normalized);
					}
					Vector3 anchor = Vector(part.Anchor);
					Vector3[] array2 = part.Vertices.Select((float[] vertex) => ((Matrix4x4)(ref inverseBone)).MultiplyPoint3x4(start + ((Matrix4x4)(ref root)).MultiplyVector(rotation * ((Vector(vertex) - anchor) * partScale)))).ToArray();
					Mesh val9 = new Mesh
					{
						name = "XMC_Villager_" + part.Name
					};
					meshes.Add(val9);
					val9.vertices = Il2CppStructArray<Vector3>.op_Implicit(array2);
					val9.uv = Il2CppStructArray<Vector2>.op_Implicit(((IEnumerable<float[]>)part.UV).Select((Func<float[], Vector2>)((float[] uv) => new Vector2(uv[0], uv[1]))).ToArray());
					val9.triangles = Il2CppStructArray<int>.op_Implicit(part.Triangles.ToArray());
					val9.RecalculateNormals();
					val9.RecalculateBounds();
					GameObject val10 = new GameObject("XMC_Villager_" + part.Name)
					{
						layer = ((Component)array[0]).gameObject.layer
					};
					objects.Add(val10);
					val10.transform.SetParent(val5, false);
					val10.AddComponent<MeshFilter>().sharedMesh = val9;
					((Renderer)val10.AddComponent<MeshRenderer>()).sharedMaterial = material;
				}
				HashSet<int> ids = new HashSet<int>(dictionary.Values.Select((Transform bone) => ((Object)bone).GetInstanceID()));
				SkinnedMeshRenderer[] array3 = array;
				foreach (SkinnedMeshRenderer val11 in array3)
				{
					if (((IEnumerable<Transform>)val11.bones).Any((Transform bone) => (Object)(object)bone != (Object)null && ids.Contains(((Object)bone).GetInstanceID())) && (Object)(object)((Component)val11).GetComponentInParent<ItemEquippable>() == (Object)null)
					{
						originals[((Object)val11).GetInstanceID()] = ((Renderer)(object)val11, ((Renderer)val11).enabled);
					}
				}
				if (originals.Count == 0)
				{
					throw new InvalidOperationException("没有可安全隐藏的身体网格");
				}
				HideOriginals();
			}
			catch
			{
				Dispose();
				throw;
			}
		}

		private static Vector3 Vector(float[] values)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(values[0], values[1], values[2]);
		}

		private static Transform? FindBone(Transform root, string semantic)
		{
			if (semantic == null)
			{
				goto IL_02c4;
			}
			int length = semantic.Length;
			string[] array;
			if (length <= 5)
			{
				if (length != 4)
				{
					if (length != 5 || !(semantic == "Chest"))
					{
						goto IL_02c4;
					}
					array = new string[4] { "spine2", "spine02", "chest", "spine1" };
				}
				else
				{
					char c = semantic[1];
					if (c != 'e')
					{
						if (c != 'i' || !(semantic == "Hips"))
						{
							goto IL_02c4;
						}
						array = new string[2] { "hips", "pelvis" };
					}
					else
					{
						if (!(semantic == "Head"))
						{
							goto IL_02c4;
						}
						array = new string[1] { "head" };
					}
				}
			}
			else if (length != 12)
			{
				if (length != 13)
				{
					goto IL_02c4;
				}
				char c = semantic[5];
				if (c != 'L')
				{
					if (c != 'U')
					{
						goto IL_02c4;
					}
					if (!(semantic == "RightUpperArm"))
					{
						if (!(semantic == "RightUpperLeg"))
						{
							goto IL_02c4;
						}
						array = new string[3] { "rightupleg", "rthigh", "rightthigh" };
					}
					else
					{
						array = new string[3] { "rightupperarm", "rupperarm", "rightarm" };
					}
				}
				else if (!(semantic == "RightLowerArm"))
				{
					if (!(semantic == "RightLowerLeg"))
					{
						goto IL_02c4;
					}
					array = new string[3] { "rightleg", "rcalf", "rightcalf" };
				}
				else
				{
					array = new string[3] { "rightforearm", "rforearm", "rightlowerarm" };
				}
			}
			else
			{
				char c = semantic[4];
				if (c != 'L')
				{
					if (c != 'U')
					{
						goto IL_02c4;
					}
					if (!(semantic == "LeftUpperArm"))
					{
						if (!(semantic == "LeftUpperLeg"))
						{
							goto IL_02c4;
						}
						array = new string[3] { "leftupleg", "lthigh", "leftthigh" };
					}
					else
					{
						array = new string[3] { "leftupperarm", "lupperarm", "leftarm" };
					}
				}
				else if (!(semantic == "LeftLowerArm"))
				{
					if (!(semantic == "LeftLowerLeg"))
					{
						goto IL_02c4;
					}
					array = new string[3] { "leftleg", "lcalf", "leftcalf" };
				}
				else
				{
					array = new string[3] { "leftforearm", "lforearm", "leftlowerarm" };
				}
			}
			goto IL_02fb;
			IL_02fb:
			string[] array2 = array;
			Il2CppArrayBase<Transform> componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(true);
			array = array2;
			foreach (string text in array)
			{
				foreach (Transform item in componentsInChildren)
				{
					string text2 = new string(((Object)item).name.Where(char.IsLetterOrDigit).Select(char.ToLowerInvariant).ToArray());
					if (text2 == text || text2.EndsWith("bip01" + text, StringComparison.Ordinal) || text2.EndsWith("mixamorig" + text, StringComparison.Ordinal))
					{
						return item;
					}
				}
			}
			return null;
			IL_02c4:
			array = new string[2]
			{
				semantic.ToLowerInvariant(),
				semantic.Replace("Left", "L").Replace("Right", "R").ToLowerInvariant()
			};
			goto IL_02fb;
		}

		private static Material CreateMaterial(Texture2D texture, SkinnedMeshRenderer[] renderers)
		{
			//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_0052: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			string[] array = new string[3] { "Standard", "Legacy Shaders/Diffuse", "Unlit/Texture" };
			for (int i = 0; i < array.Length; i++)
			{
				Shader val = Shader.Find(array[i]);
				if (!((Object)(object)val == (Object)null) && val.isSupported)
				{
					Material val2 = new Material(val)
					{
						name = "XMC_Villager_PixelCloth"
					};
					val2.mainTexture = (Texture)(object)texture;
					if (val2.HasProperty("_Color"))
					{
						val2.SetColor("_Color", Color.white);
					}
					if (val2.HasProperty("_Glossiness"))
					{
						val2.SetFloat("_Glossiness", 0f);
					}
					if (val2.HasProperty("_Metallic"))
					{
						val2.SetFloat("_Metallic", 0f);
					}
					return val2;
				}
			}
			for (int i = 0; i < renderers.Length; i++)
			{
				foreach (Material item in (Il2CppArrayBase<Material>)(object)((Renderer)renderers[i]).sharedMaterials)
				{
					if (!((Object)(object)item == (Object)null) && !((Object)(object)item.shader == (Object)null) && item.shader.isSupported && item.HasProperty("_MainTex"))
					{
						Material val3 = new Material(item)
						{
							name = "XMC_Villager_NativeCloth"
						};
						val3.SetTexture("_MainTex", (Texture)(object)texture);
						if (val3.HasProperty("_Color"))
						{
							val3.SetColor("_Color", Color.white);
						}
						if (val3.HasProperty("_EmissionColor"))
						{
							val3.SetColor("_EmissionColor", Color.black);
						}
						val3.DisableKeyword("_EMISSION");
						return val3;
					}
				}
			}
			throw new InvalidOperationException("未找到可显示像素贴图的兼容材质");
		}

		internal bool Valid(PlayerAgent player)
		{
			if (!disposed && (Object)(object)animator != (Object)null && (Object)(object)player.AnimatorBody != (Object)null && ((Object)animator).GetInstanceID() == ((Object)player.AnimatorBody).GetInstanceID())
			{
				return objects.All((GameObject obj) => (Object)(object)obj != (Object)null);
			}
			return false;
		}

		internal void HideOriginals()
		{
			if (disposed)
			{
				return;
			}
			foreach (var value in originals.Values)
			{
				if ((Object)(object)value.Renderer != (Object)null)
				{
					value.Renderer.enabled = false;
				}
			}
		}

		public void Dispose()
		{
			if (disposed)
			{
				return;
			}
			disposed = true;
			foreach (var value in originals.Values)
			{
				if ((Object)(object)value.Renderer != (Object)null)
				{
					value.Renderer.enabled = value.Enabled;
				}
			}
			originals.Clear();
			foreach (GameObject @object in objects)
			{
				if ((Object)(object)@object != (Object)null)
				{
					Object.Destroy((Object)(object)@object);
				}
			}
			foreach (Mesh mesh in meshes)
			{
				if ((Object)(object)mesh != (Object)null)
				{
					Object.Destroy((Object)(object)mesh);
				}
			}
			objects.Clear();
			meshes.Clear();
			if ((Object)(object)material != (Object)null)
			{
				Object.Destroy((Object)(object)material);
			}
		}
	}
}