Decompiled source of ValheimPlayerModelReupload v1.0.1

ValheimPlayerModels.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Animations;
using UnityEngine.Scripting;
using ValheimPlayerModels.Loaders;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: IgnoresAccessChecksTo("assembly_googleanalytics")]
[assembly: IgnoresAccessChecksTo("assembly_guiutils")]
[assembly: IgnoresAccessChecksTo("assembly_lux")]
[assembly: IgnoresAccessChecksTo("assembly_postprocessing")]
[assembly: IgnoresAccessChecksTo("assembly_simplemeshcombine")]
[assembly: IgnoresAccessChecksTo("assembly_steamworks")]
[assembly: IgnoresAccessChecksTo("assembly_sunshafts")]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: AssemblyCompany("ValheimPlayerModels")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Use custom player models in Valheim !")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Valheim Player Models")]
[assembly: AssemblyTitle("ValheimPlayerModels")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Ikeiwa/ValheimPlayerModels")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ValheimPlayerModels
{
	internal sealed class ConfigurationManagerAttributes
	{
		public bool? ShowRangeAsPercent;

		public Action<ConfigEntryBase> CustomDrawer;

		public bool? Browsable;

		public string Category;

		public object DefaultValue;

		public bool? HideDefaultButton;

		public bool? HideSettingName;

		public string Description;

		public string DispName;

		public int? Order;

		public bool? ReadOnly;

		public bool? IsAdvanced;

		public Func<object, string> ObjToStr;

		public Func<string, object> StrToObj;
	}
	public class CustomRagdoll : MonoBehaviour
	{
		private Ragdoll ragdoll;

		private Animator ragdollAnimator;

		private Animator avatarAnimator;

		private bool hidden = false;

		public void Setup(Animator ogAnimator, Animator avatarAnimator)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)avatarAnimator))
			{
				Object.Destroy((Object)(object)this);
			}
			((Component)avatarAnimator).transform.SetParent(((Component)this).transform);
			((Component)avatarAnimator).transform.localPosition = Vector3.zero;
			((Component)avatarAnimator).transform.localRotation = Quaternion.identity;
			ragdoll = ((Component)this).GetComponent<Ragdoll>();
			this.avatarAnimator = avatarAnimator;
			ragdollAnimator = ((Component)((Component)ragdoll).gameObject.transform.GetChild(0)).gameObject.AddComponent<Animator>();
			ragdollAnimator.avatar = ogAnimator.avatar;
			avatarAnimator.GetBoneTransform((HumanBodyBones)0).position = ragdollAnimator.GetBoneTransform((HumanBodyBones)0).position;
			for (int i = 0; i < 55; i++)
			{
				Transform boneTransform = ragdollAnimator.GetBoneTransform((HumanBodyBones)i);
				Transform boneTransform2 = avatarAnimator.GetBoneTransform((HumanBodyBones)i);
				if (Object.op_Implicit((Object)(object)boneTransform) && Object.op_Implicit((Object)(object)boneTransform2))
				{
					RotationConstraint val = ((Component)boneTransform2).gameObject.AddComponent<RotationConstraint>();
					ConstraintSource val2 = default(ConstraintSource);
					((ConstraintSource)(ref val2)).sourceTransform = boneTransform;
					((ConstraintSource)(ref val2)).weight = 1f;
					val.AddSource(val2);
					Quaternion val3 = Quaternion.identity * Quaternion.Inverse(boneTransform.rotation);
					Quaternion val4 = Quaternion.identity * Quaternion.Inverse(boneTransform2.rotation);
					Quaternion val5 = val3 * Quaternion.Inverse(val4);
					val.rotationOffset = ((Quaternion)(ref val5)).eulerAngles;
					val.locked = true;
					val.constraintActive = true;
					if (i == 0)
					{
						PositionConstraint val6 = ((Component)boneTransform2).gameObject.AddComponent<PositionConstraint>();
						val2 = default(ConstraintSource);
						((ConstraintSource)(ref val2)).sourceTransform = boneTransform;
						((ConstraintSource)(ref val2)).weight = 1f;
						val6.AddSource(val2);
						val6.translationOffset = boneTransform2.position - boneTransform.position;
						val6.locked = true;
						val6.constraintActive = true;
					}
				}
			}
		}

		private void LateUpdate()
		{
			if (!hidden)
			{
				Renderer[] componentsInChildren = ((Component)((Component)ragdollAnimator).transform).GetComponentsInChildren<Renderer>();
				foreach (Renderer val in componentsInChildren)
				{
					val.enabled = false;
				}
				hidden = true;
			}
		}
	}
	public static class HarmonyUtils
	{
		public static Tout GetField<Tin, Tout>(this Tin self, string fieldName)
		{
			return AccessTools.FieldRefAccess<Tin, Tout>(fieldName).Invoke(self);
		}
	}
	[DefaultExecutionOrder(2147483646)]
	public class PlayerModel : MonoBehaviour
	{
		public class AttachTransform
		{
			public Transform ogAttach;

			public Transform pmAttach;

			public Vector3 ogPosition;

			public Quaternion ogRotation;

			public Vector3 ogScale;
		}

		public static PlayerModel localModel;

		public string selectedAvatar = "";

		private VisEquipment visEquipment;

		private GameObject ogVisual;

		private int selectedHash = Animator.StringToHash("SelectedCustomAvatar");

		private bool playerModelVisible = true;

		private Animator ogAnimator;

		private List<AttachTransform> ogAttachments;

		private HumanPoseHandler ogPose;

		private HumanPoseHandler pmPose;

		private HumanPose pose = default(HumanPose);

		private float footOffset;

		private bool dead = false;

		private bool requestHide;

		public bool enableTracking = true;

		public Player player { get; private set; }

		public ZNetView zNetView { get; private set; }

		public AvatarInstance avatar { get; private set; }

		public bool playerModelLoaded { get; private set; }

		private void Awake()
		{
			player = ((Component)this).GetComponent<Player>();
			visEquipment = ((Component)this).GetComponent<VisEquipment>();
			zNetView = ((Component)this).GetComponent<ZNetView>();
			ogVisual = ((Component)((Character)player).m_animator).gameObject;
			ogAnimator = ((Character)player).m_animator;
			ogAnimator.keepAnimatorControllerStateOnDisable = true;
			ogAnimator.cullingMode = (AnimatorCullingMode)0;
			((MonoBehaviour)this).StartCoroutine(LoadAvatar());
		}

		private void OnDestroy()
		{
			if ((Object)(object)localModel == (Object)(object)this)
			{
				Plugin.showActionMenu = false;
				Plugin.showAvatarMenu = false;
				Plugin.ResetCursor();
			}
			RemoveAvatar();
			((MonoBehaviour)this).StopAllCoroutines();
		}

		private void Update()
		{
		}

		private void FixedUpdate()
		{
			if (!((Object)(object)Game.instance != (Object)null) || !playerModelLoaded || !playerModelVisible || dead || !zNetView.IsValid() || zNetView.IsOwner())
			{
				return;
			}
			ZDO zDO = zNetView.GetZDO();
			foreach (KeyValuePair<int, AvatarInstance.AvatarParameter> parameter in avatar.Parameters)
			{
				switch (parameter.Value.type)
				{
				case AvatarInstance.ParameterType.Bool:
				{
					bool @bool = zDO.GetBool(438569 + parameter.Key, false);
					avatar.Animator.SetBool(parameter.Key, @bool);
					break;
				}
				case AvatarInstance.ParameterType.Int:
				{
					int @int = zDO.GetInt(438569 + parameter.Key, 0);
					avatar.Animator.SetInteger(parameter.Key, @int);
					break;
				}
				case AvatarInstance.ParameterType.Float:
				{
					float @float = zDO.GetFloat(438569 + parameter.Key, 0f);
					avatar.Animator.SetFloat(parameter.Key, @float);
					break;
				}
				default:
					throw new ArgumentOutOfRangeException();
				}
			}
			string @string = zDO.GetString(selectedHash, (string)null);
			if (@string != null && @string != selectedAvatar)
			{
				selectedAvatar = @string;
				ReloadAvatar();
			}
		}

		private void LateUpdate()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			if (!playerModelLoaded || !playerModelVisible || dead)
			{
				return;
			}
			if (enableTracking)
			{
				avatar.Transform.localPosition = Vector3.zero;
				ogPose.GetHumanPose(ref pose);
				pmPose.SetHumanPose(ref pose);
				Transform boneTransform = ogAnimator.GetBoneTransform((HumanBodyBones)0);
				if (Object.op_Implicit((Object)(object)boneTransform))
				{
					avatar.Hips.position = new Vector3(avatar.Hips.position.x, boneTransform.position.y, avatar.Hips.position.z);
					float num = Mathf.Min(new float[3]
					{
						avatar.LeftFoot.position.y - avatar.Transform.position.y,
						avatar.RightFoot.position.y - avatar.Transform.position.y,
						0f
					});
					avatar.Hips.Translate(0f, 0f - num + footOffset, 0f, (Space)0);
				}
			}
			foreach (AttachTransform ogAttachment in ogAttachments)
			{
				if ((Object)(object)ogAttachment.pmAttach != (Object)null)
				{
					ogAttachment.ogAttach.position = ogAttachment.pmAttach.position;
					ogAttachment.ogAttach.rotation = ogAttachment.pmAttach.rotation;
					ogAttachment.ogAttach.localScale = Vector3.Scale(ogAttachment.ogScale, ogAttachment.pmAttach.localScale);
				}
			}
			if (requestHide)
			{
				ToggleEquipments();
			}
			if (((Character)player).IsDead() && !dead)
			{
				dead = true;
				if (!PluginConfig.enableCustomRagdoll.Value)
				{
					Hide();
				}
			}
		}

		private IEnumerator LoadAvatar()
		{
			yield return (object)new WaitForSecondsRealtime(0.5f);
			Plugin.RefreshBundlePaths();
			if ((Object)(object)player == (Object)(object)Player.m_localPlayer || (Object)(object)Game.instance == (Object)null)
			{
				selectedAvatar = PluginConfig.selectedAvatar.Value;
				localModel = this;
			}
			if ((Object)(object)zNetView != (Object)null && zNetView.IsValid() && !zNetView.IsOwner() && (Object)(object)Game.instance != (Object)null)
			{
				int tries = 0;
				string syncedAvatar = null;
				while (syncedAvatar == null && tries < 100)
				{
					syncedAvatar = zNetView.GetZDO().GetString(selectedHash, (string)null);
					tries++;
					yield return (object)new WaitForSecondsRealtime(0.05f);
				}
				if (syncedAvatar != null)
				{
					selectedAvatar = syncedAvatar;
				}
			}
			if (string.IsNullOrEmpty(selectedAvatar))
			{
				if ((Object)(object)Game.instance != (Object)null)
				{
					selectedAvatar = player.GetPlayerName();
					if (selectedAvatar == "" || selectedAvatar == "...")
					{
						selectedAvatar = Game.instance.GetPlayerProfile().GetName();
					}
				}
				else
				{
					int index = FejdStartup.instance.GetField<FejdStartup, int>("m_profileIndex");
					List<PlayerProfile> profiles = FejdStartup.instance.GetField<FejdStartup, List<PlayerProfile>>("m_profiles");
					if (index >= 0 && index < profiles.Count)
					{
						selectedAvatar = profiles[index].GetName();
					}
				}
				selectedAvatar = selectedAvatar.ToLower();
				string playerId = "";
				if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer() && (int)ZNet.GetConnectionStatus() == 2)
				{
					int tries2 = 0;
					do
					{
						List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
						int playerIndex = playerList.FindIndex((PlayerInfo p) => ((ZDOID)(ref p.m_characterID)).UserID == ((ZDOID)(ref zNetView.m_zdo.m_uid)).UserID);
						if (playerIndex != -1)
						{
							playerId = playerList[playerIndex].m_host;
							tries2++;
						}
						else
						{
							tries2++;
							yield return null;
						}
					}
					while (string.IsNullOrEmpty(playerId) && tries2 < 100);
					if (!string.IsNullOrEmpty(playerId) && Plugin.playerModelBundlePaths.ContainsKey(playerId))
					{
						selectedAvatar = playerId;
					}
				}
			}
			if ((Object)(object)zNetView != (Object)null && zNetView.IsValid() && zNetView.IsOwner() && (Object)(object)Game.instance != (Object)null)
			{
				zNetView.GetZDO().Set(selectedHash, selectedAvatar);
			}
			Plugin.Log.LogMessage((object)("Loading " + selectedAvatar + " avatar"));
			if (!Plugin.playerModelBundlePaths.ContainsKey(selectedAvatar))
			{
				Plugin.Log.LogError((object)("Bundle list doesn't contain bundle for : " + selectedAvatar));
				Object.Destroy((Object)(object)this);
				yield break;
			}
			AvatarLoaderBase loader;
			if (Plugin.playerModelBundleCache.ContainsKey(selectedAvatar))
			{
				while (Plugin.playerModelBundleCache[selectedAvatar] == null)
				{
					yield return null;
				}
				loader = Plugin.playerModelBundleCache[selectedAvatar];
			}
			else
			{
				if (!Plugin.playerModelBundleCache.ContainsKey(selectedAvatar))
				{
					Plugin.playerModelBundleCache.Add(selectedAvatar, null);
				}
				string avatarFile = Plugin.playerModelBundlePaths[selectedAvatar];
				string text = Path.GetExtension(avatarFile).ToLower();
				string text2 = text;
				string text3 = text2;
				if (!(text3 == ".valavtr"))
				{
					if (!(text3 == ".vrm"))
					{
						Object.Destroy((Object)(object)this);
						yield break;
					}
					loader = new VrmLoader();
				}
				else
				{
					loader = new ValavtrLoader();
				}
				yield return ((MonoBehaviour)this).StartCoroutine(loader.LoadFile(avatarFile));
				if (!loader.LoadedSuccessfully)
				{
					Plugin.playerModelBundleCache.Remove(selectedAvatar);
					Object.Destroy((Object)(object)this);
				}
				Plugin.playerModelBundleCache[selectedAvatar] = loader;
			}
			avatar = loader.LoadAvatar(this);
			if (avatar == null)
			{
				Object.Destroy((Object)(object)this);
			}
			ApplyAvatar();
			playerModelLoaded = true;
		}

		private void SetAttachParent(Transform attach, Transform newAttach)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			ogAttachments.Add(new AttachTransform
			{
				ogAttach = attach,
				pmAttach = newAttach,
				ogPosition = attach.localPosition,
				ogRotation = attach.localRotation,
				ogScale = attach.localScale
			});
		}

		private void ApplyAvatar()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Expected O, but got Unknown
			avatar.Animator.applyRootMotion = true;
			avatar.Animator.updateMode = ogAnimator.updateMode;
			avatar.Animator.feetPivotActive = ogAnimator.feetPivotActive;
			avatar.Animator.layersAffectMassCenter = ogAnimator.layersAffectMassCenter;
			avatar.Animator.stabilizeFeet = ogAnimator.stabilizeFeet;
			if (ogPose == null)
			{
				ogPose = new HumanPoseHandler(ogAnimator.avatar, ((Component)ogAnimator).transform);
			}
			if (pmPose == null)
			{
				pmPose = new HumanPoseHandler(avatar.Animator.avatar, ((Component)avatar.Animator).transform);
			}
			footOffset = (avatar.LeftFoot.position.y - avatar.Transform.position.y + (avatar.RightFoot.position.y - avatar.Transform.position.y)) / 2f;
			ogAttachments = new List<AttachTransform>();
			SetAttachParent(visEquipment.m_backAtgeir, avatar.AvatarDescriptor.backAtgeir);
			SetAttachParent(visEquipment.m_backBow, avatar.AvatarDescriptor.backBow);
			SetAttachParent(visEquipment.m_backMelee, avatar.AvatarDescriptor.backMelee);
			SetAttachParent(visEquipment.m_backShield, avatar.AvatarDescriptor.backShield);
			SetAttachParent(visEquipment.m_backTool, avatar.AvatarDescriptor.backTool);
			SetAttachParent(visEquipment.m_backTwohandedMelee, avatar.AvatarDescriptor.backTwohandedMelee);
			SetAttachParent(visEquipment.m_helmet, avatar.AvatarDescriptor.helmet);
			SetAttachParent(visEquipment.m_leftHand, avatar.AvatarDescriptor.leftHand);
			SetAttachParent(visEquipment.m_rightHand, avatar.AvatarDescriptor.rightHand);
			ToggleAvatar();
		}

		public void ToggleAvatar(bool visible = true)
		{
			playerModelVisible = visible;
			Animator animator = avatar.Animator;
			if (animator != null)
			{
				((Component)animator).gameObject.SetActive(visible);
			}
			SkinnedMeshRenderer[] componentsInChildren = ogVisual.GetComponentsInChildren<SkinnedMeshRenderer>();
			foreach (SkinnedMeshRenderer val in componentsInChildren)
			{
				((Renderer)val).forceRenderingOff = visible;
				val.updateWhenOffscreen = true;
			}
			ToggleEquipments(!visible);
		}

		public void Hide()
		{
			((Component)avatar.Animator).gameObject.SetActive(false);
		}

		public void Show()
		{
			if (Object.op_Implicit((Object)(object)avatar.Animator))
			{
				((Component)avatar.Animator).gameObject.SetActive(true);
			}
		}

		public void ToggleEquipments(bool visible = false)
		{
			//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			if (!playerModelLoaded)
			{
				requestHide = true;
			}
			else
			{
				if (!Object.op_Implicit((Object)(object)visEquipment))
				{
					return;
				}
				GameObject beardItemInstance = visEquipment.m_beardItemInstance;
				if (beardItemInstance != null)
				{
					beardItemInstance.SetActive(visible);
				}
				GameObject hairItemInstance = visEquipment.m_hairItemInstance;
				if (hairItemInstance != null)
				{
					hairItemInstance.SetActive(visible);
				}
				GameObject helmetItemInstance = visEquipment.m_helmetItemInstance;
				if (helmetItemInstance != null)
				{
					helmetItemInstance.SetActive(visible || avatar.AvatarDescriptor.showHelmet);
				}
				if (visEquipment.m_shoulderItemInstances != null)
				{
					foreach (GameObject shoulderItemInstance in visEquipment.m_shoulderItemInstances)
					{
						if (visEquipment.m_shoulderItem.ToLower().Contains("cape"))
						{
							if (shoulderItemInstance != null)
							{
								shoulderItemInstance.SetActive(visible || avatar.AvatarDescriptor.showCape);
							}
							SkinnedMeshRenderer[] componentsInChildren = shoulderItemInstance.GetComponentsInChildren<SkinnedMeshRenderer>();
							foreach (SkinnedMeshRenderer val in componentsInChildren)
							{
								((Renderer)val).forceRenderingOff = false;
								val.updateWhenOffscreen = true;
							}
						}
						else if (shoulderItemInstance != null)
						{
							shoulderItemInstance.SetActive(visible);
						}
					}
				}
				if (visEquipment.m_legItemInstances != null)
				{
					foreach (GameObject legItemInstance in visEquipment.m_legItemInstances)
					{
						if (legItemInstance != null)
						{
							legItemInstance.SetActive(visible);
						}
					}
				}
				if (visEquipment.m_chestItemInstances != null)
				{
					foreach (GameObject chestItemInstance in visEquipment.m_chestItemInstances)
					{
						if (chestItemInstance != null)
						{
							chestItemInstance.SetActive(visible);
						}
					}
				}
				if (visEquipment.m_utilityItemInstances != null)
				{
					foreach (GameObject utilityItemInstance in visEquipment.m_utilityItemInstances)
					{
						if (utilityItemInstance != null)
						{
							utilityItemInstance.SetActive(visible);
						}
					}
				}
				if (visible)
				{
					foreach (AttachTransform ogAttachment in ogAttachments)
					{
						ogAttachment.ogAttach.localPosition = ogAttachment.ogPosition;
						ogAttachment.ogAttach.localRotation = ogAttachment.ogRotation;
						ogAttachment.ogAttach.localScale = ogAttachment.ogScale;
					}
					SkinnedMeshRenderer[] componentsInChildren2 = ogVisual.GetComponentsInChildren<SkinnedMeshRenderer>();
					foreach (SkinnedMeshRenderer val2 in componentsInChildren2)
					{
						((Renderer)val2).forceRenderingOff = false;
						val2.updateWhenOffscreen = true;
					}
				}
				requestHide = false;
			}
		}

		public void SetupRagdoll(Ragdoll ragdoll)
		{
			((Component)ragdoll).gameObject.AddComponent<CustomRagdoll>().Setup(ogAnimator, avatar.Animator);
		}

		public void RemoveAvatar(bool forced = false)
		{
			if ((!PluginConfig.enableCustomRagdoll.Value || forced) && avatar != null)
			{
				Object.Destroy((Object)(object)avatar.AvatarObject);
			}
			avatar = null;
			if (ogPose != null)
			{
				ogPose.Dispose();
				ogPose = null;
			}
			if (pmPose != null)
			{
				pmPose.Dispose();
				pmPose = null;
			}
			playerModelLoaded = false;
		}

		public void ReloadAvatar()
		{
			if (playerModelLoaded)
			{
				ToggleAvatar(visible: false);
				RemoveAvatar(forced: true);
				((MonoBehaviour)this).StartCoroutine(LoadAvatar());
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Awake")]
	internal static class Patch_Player_Awake
	{
		[HarmonyPostfix]
		private static void Postfix(Player __instance)
		{
			if (PluginConfig.enablePlayerModels.Value)
			{
				((Component)__instance).gameObject.AddComponent<PlayerModel>();
			}
		}
	}
	[HarmonyPatch(typeof(VisEquipment), "UpdateLodgroup")]
	internal static class Patch_VisEquipment_UpdateLodgroup
	{
		[HarmonyPostfix]
		private static void Postfix(VisEquipment __instance)
		{
			if (PluginConfig.enablePlayerModels.Value)
			{
				((Component)__instance).GetComponent<PlayerModel>()?.ToggleEquipments();
			}
		}
	}
	[HarmonyPatch(typeof(Ragdoll), "Start")]
	internal static class Patch_Ragdoll_Start
	{
		[HarmonyPostfix]
		private static void Postfix(Ragdoll __instance)
		{
			if (PluginConfig.enableCustomRagdoll.Value && ((Object)((Component)__instance).gameObject).name.StartsWith("Player") && Object.op_Implicit((Object)(object)ZNet.instance))
			{
				PlayerModel[] source = Object.FindObjectsOfType<PlayerModel>();
				PlayerModel playerModel = source.FirstOrDefault(delegate(PlayerModel p)
				{
					//IL_0006: 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)
					ZDOID zDOID = ((Character)p.player).GetZDOID();
					return ((ZDOID)(ref zDOID)).UserID == ((ZDOID)(ref __instance.m_nview.m_zdo.m_uid)).UserID;
				});
				if (Object.op_Implicit((Object)(object)playerModel))
				{
					playerModel.SetupRagdoll(__instance);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "TryRunCommand")]
	internal static class Patch_Terminal_TryRunCommand
	{
		[HarmonyPostfix]
		private static void Postfix(Terminal __instance, string text, bool silentFail = false, bool skipAllowedCheck = false)
		{
			string text2 = text.ToLower();
			string[] array = text2.Split(new char[1] { ' ' });
			if (text2.StartsWith("anim") && array.Length == 3 && Object.op_Implicit((Object)(object)PlayerModel.localModel) && (!bool.TryParse(array[2], out var result) || !PlayerModel.localModel.avatar.SetBool(array[1], result)) && (!int.TryParse(array[2], out var result2) || !PlayerModel.localModel.avatar.SetInt(array[1], result2)) && float.TryParse(array[2], out var result3))
			{
				PlayerModel.localModel.avatar.SetFloat(array[1], result3);
			}
		}
	}
	[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
	internal static class Patch_GameCamera_UpdateMouseCapture
	{
		[HarmonyPrefix]
		private static bool Prefix(GameCamera __instance)
		{
			if (PluginConfig.enablePlayerModels.Value && (Plugin.showActionMenu || Plugin.showAvatarMenu))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Player), "SetMouseLook")]
	internal static class Patch_Player_SetMouseLook
	{
		[HarmonyPrefix]
		private static bool Prefix(Player __instance)
		{
			if (PluginConfig.enablePlayerModels.Value && (Plugin.showActionMenu || Plugin.showAvatarMenu))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "SetVisible")]
	internal static class Patch_Character_SetVisible
	{
		[HarmonyPostfix]
		private static void Postfix(Character __instance, bool visible)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.IsPlayer())
			{
				return;
			}
			PlayerModel playerModel;
			if (!Plugin.playerModelCharacters.ContainsKey(__instance))
			{
				playerModel = ((Component)__instance.GetVisual().transform.parent).GetComponent<PlayerModel>();
				Plugin.playerModelCharacters.Add(__instance, playerModel);
			}
			else
			{
				playerModel = Plugin.playerModelCharacters[__instance];
			}
			if (!Object.op_Implicit((Object)(object)playerModel) || playerModel.avatar == null)
			{
				return;
			}
			LODGroup lodGroup = playerModel.avatar.lodGroup;
			if (Object.op_Implicit((Object)(object)lodGroup))
			{
				if (visible)
				{
					lodGroup.localReferencePoint = __instance.m_originalLocalRef;
				}
				else
				{
					lodGroup.localReferencePoint = new Vector3(999999f, 999999f, 999999f);
				}
			}
		}
	}
	[BepInPlugin("ValheimPlayerModels", "Valheim Player Models", "1.0.1")]
	[BepInProcess("valheim.exe")]
	public class Plugin : BaseUnityPlugin
	{
		public static ManualLogSource Log;

		public static Dictionary<string, AvatarLoaderBase> playerModelBundleCache = new Dictionary<string, AvatarLoaderBase>();

		public static Dictionary<Character, PlayerModel> playerModelCharacters = new Dictionary<Character, PlayerModel>();

		public static bool showActionMenu;

		public static bool showAvatarMenu;

		private Rect ActionWindowRect;

		private Rect AvatarWindowRect;

		private static CursorLockMode oldCursorLockState = (CursorLockMode)2;

		private static bool oldCursorVisible = false;

		public const int ActionWindowId = -48;

		public const int AvatarWindowId = -49;

		private Vector2 actionMenuWindowScrollPos;

		private Vector2 avatarMenuWindowScrollPos;

		private int hasChangedParam = 0;

		public static string playerModelsPath => Path.Combine(Environment.CurrentDirectory, "PlayerModels");

		public static Dictionary<string, string> playerModelBundlePaths { get; private set; }

		private void Awake()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			GarbageCollector.incrementalTimeSliceNanoseconds = 5000000uL;
			PluginConfig.InitConfig(((BaseUnityPlugin)this).Config);
			((BaseUnityPlugin)this).Config.SettingChanged += ConfigOnSettingChanged;
			if (!Directory.Exists(playerModelsPath))
			{
				Directory.CreateDirectory(playerModelsPath);
			}
			RefreshBundlePaths(silent: false);
			Harmony val = new Harmony("ValheimPlayerModels.patch");
			val.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin ValheimPlayerModels is loaded!");
		}

		private void Update()
		{
			//IL_0006: 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)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = PluginConfig.reloadKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && PluginConfig.enablePlayerModels.Value)
			{
				PlayerModel[] array = Object.FindObjectsOfType<PlayerModel>();
				bool flag = true;
				PlayerModel[] array2 = array;
				foreach (PlayerModel playerModel in array2)
				{
					if (!playerModel.playerModelLoaded)
					{
						flag = false;
						break;
					}
				}
				if (!flag)
				{
					return;
				}
				PlayerModel[] array3 = array;
				foreach (PlayerModel playerModel2 in array3)
				{
					playerModel2.ToggleAvatar(visible: false);
					Object.Destroy((Object)(object)playerModel2);
				}
				foreach (AvatarLoaderBase value2 in playerModelBundleCache.Values)
				{
					value2?.Unload();
				}
				playerModelBundleCache.Clear();
				RefreshBundlePaths();
				Player[] array4 = Object.FindObjectsOfType<Player>();
				Player[] array5 = array4;
				foreach (Player val in array5)
				{
					((Component)val).gameObject.AddComponent<PlayerModel>();
				}
			}
			value = PluginConfig.actionMenuKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !showAvatarMenu && (Object)(object)PlayerModel.localModel != (Object)null && (Object)(object)Game.instance != (Object)null)
			{
				showActionMenu = !showActionMenu;
				if (showActionMenu)
				{
					SetUnlockCursor();
					GUI.FocusWindow(-48);
				}
				else
				{
					ResetCursor();
				}
			}
			value = PluginConfig.avatarMenuKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown() && !showActionMenu)
			{
				showAvatarMenu = !showAvatarMenu;
				if (showAvatarMenu)
				{
					SetUnlockCursor();
					GUI.FocusWindow(-49);
				}
				else
				{
					ResetCursor();
				}
			}
			if (showActionMenu && hasChangedParam > 0)
			{
				hasChangedParam--;
			}
		}

		private void ConfigOnSettingChanged(object sender, SettingChangedEventArgs e)
		{
			if (e.ChangedSetting.Definition.Key == "EnablePlayerModels")
			{
				PlayerModel[] array = Object.FindObjectsOfType<PlayerModel>();
				if ((bool)e.ChangedSetting.BoxedValue)
				{
					PlayerModel[] array2 = array;
					foreach (PlayerModel playerModel in array2)
					{
						playerModel.ToggleAvatar();
					}
					Player[] array3 = Object.FindObjectsOfType<Player>();
					Player[] array4 = array3;
					foreach (Player val in array4)
					{
						if ((Object)(object)((Component)val).GetComponent<PlayerModel>() == (Object)null)
						{
							((Component)val).gameObject.AddComponent<PlayerModel>();
						}
					}
				}
				else
				{
					PlayerModel[] array5 = array;
					foreach (PlayerModel playerModel2 in array5)
					{
						playerModel2.ToggleAvatar(visible: false);
					}
				}
			}
			else if (e.ChangedSetting.Definition.Key == "SelectedAvatar")
			{
				PlayerModel playerModel3 = null;
				playerModel3 = ((!((Object)(object)Player.m_localPlayer != (Object)null)) ? Object.FindObjectOfType<PlayerModel>() : ((Component)Player.m_localPlayer).gameObject.GetComponent<PlayerModel>());
				if ((Object)(object)playerModel3 != (Object)null && playerModel3.playerModelLoaded)
				{
					playerModel3.ReloadAvatar();
				}
			}
		}

		public static void RefreshBundlePaths(bool silent = true)
		{
			playerModelBundlePaths = new Dictionary<string, string>();
			string[] array = (from s in Directory.GetFiles(playerModelsPath, "*.*", SearchOption.AllDirectories)
				where s.EndsWith(".valavtr") || s.EndsWith(".vrm")
				select s).ToArray();
			string[] array2 = array;
			foreach (string text in array2)
			{
				string text2 = Path.GetFileNameWithoutExtension(text).ToLower();
				if (!silent)
				{
					Log.LogMessage((object)("Found avatar : " + text2));
				}
				if (!playerModelBundlePaths.ContainsKey(text2))
				{
					playerModelBundlePaths.Add(text2, text);
				}
			}
		}

		public static void SetUnlockCursor()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Cursor.lockState != 0)
			{
				oldCursorLockState = Cursor.lockState;
				oldCursorVisible = Cursor.visible;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		public static void ResetCursor()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Cursor.lockState = oldCursorLockState;
			Cursor.visible = oldCursorVisible;
		}

		private void OnGUI()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: 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_0204: Expected O, but got Unknown
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			if (showActionMenu && (Object)(object)PlayerModel.localModel != (Object)null)
			{
				ActionWindowRect = new Rect((float)Screen.width, (float)Screen.height, 250f, 400f);
				ref Rect actionWindowRect = ref ActionWindowRect;
				((Rect)(ref actionWindowRect)).x = ((Rect)(ref actionWindowRect)).x - ((Rect)(ref ActionWindowRect)).width;
				ref Rect actionWindowRect2 = ref ActionWindowRect;
				((Rect)(ref actionWindowRect2)).y = ((Rect)(ref actionWindowRect2)).y - ((Rect)(ref ActionWindowRect)).height;
				if ((GUI.Button(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), string.Empty, GUIStyle.none) && !((Rect)(ref ActionWindowRect)).Contains(Input.mousePosition)) || Input.GetKeyDown((KeyCode)27))
				{
					showActionMenu = false;
					ResetCursor();
				}
				GUI.enabled = PlayerModel.localModel.playerModelLoaded;
				GUI.Box(ActionWindowRect, GUIContent.none);
				GUILayout.Window(-48, ActionWindowRect, new WindowFunction(ActionMenuWindow), "Action Menu", Array.Empty<GUILayoutOption>());
				Input.ResetInputAxes();
			}
			if (showAvatarMenu)
			{
				AvatarWindowRect = new Rect(20f, 100f, 250f, 400f);
				if ((GUI.Button(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), string.Empty, GUIStyle.none) && !((Rect)(ref AvatarWindowRect)).Contains(Input.mousePosition)) || Input.GetKeyDown((KeyCode)27))
				{
					showAvatarMenu = false;
					ResetCursor();
				}
				if (Object.op_Implicit((Object)(object)PlayerModel.localModel))
				{
					GUI.enabled = PlayerModel.localModel.playerModelLoaded;
				}
				else
				{
					GUI.enabled = true;
				}
				GUI.Box(AvatarWindowRect, GUIContent.none);
				GUILayout.Window(-49, AvatarWindowRect, new WindowFunction(AvatarMenuWindow), "Avatar Menu", Array.Empty<GUILayoutOption>());
				Input.ResetInputAxes();
			}
		}

		private void ActionMenuWindow(int id)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			AvatarInstance avatar = PlayerModel.localModel.avatar;
			actionMenuWindowScrollPos = GUILayout.BeginScrollView(actionMenuWindowScrollPos, false, true, Array.Empty<GUILayoutOption>());
			float y = actionMenuWindowScrollPos.y;
			float height = ((Rect)(ref ActionWindowRect)).height;
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			float num = 21f;
			float num2 = 0f;
			for (int i = 0; i < avatar.MenuControls.Count; i++)
			{
				int num3 = Animator.StringToHash(avatar.MenuControls[i].parameter);
				if (string.IsNullOrEmpty(avatar.MenuControls[i].name) || string.IsNullOrEmpty(avatar.MenuControls[i].parameter) || !avatar.Parameters.ContainsKey(num3))
				{
					continue;
				}
				if (num == 0f || (num2 + num >= y && num2 <= y + height))
				{
					try
					{
						GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
						GUILayout.Label(avatar.MenuControls[i].name, Array.Empty<GUILayoutOption>());
						float parameterValue = avatar.GetParameterValue(num3);
						switch (avatar.MenuControls[i].type)
						{
						case ControlType.Button:
							if (GUILayout.Button("Press", Array.Empty<GUILayoutOption>()))
							{
								if (parameterValue == 0f)
								{
									avatar.SetParameterValue(num3, avatar.MenuControls[i].value);
									hasChangedParam = 5;
								}
							}
							else if (parameterValue != 0f && hasChangedParam <= 0)
							{
								avatar.SetParameterValue(num3, 0f);
							}
							break;
						case ControlType.Toggle:
						{
							bool flag = parameterValue != 0f;
							bool flag2 = GUILayout.Toggle(flag, string.Empty, Array.Empty<GUILayoutOption>());
							if (flag2 != flag)
							{
								avatar.SetParameterValue(num3, flag2 ? avatar.MenuControls[i].value : 0f);
							}
							break;
						}
						case ControlType.Slider:
						{
							float num4 = GUILayout.HorizontalSlider(parameterValue, 0f, 1f, Array.Empty<GUILayoutOption>());
							if (Mathf.Abs(num4 - parameterValue) > 0.01f)
							{
								avatar.SetParameterValue(num3, num4);
							}
							break;
						}
						default:
							throw new ArgumentOutOfRangeException();
						}
						GUILayout.EndHorizontal();
					}
					catch (ArgumentException)
					{
					}
				}
				else
				{
					try
					{
						GUILayout.Space(num);
					}
					catch (ArgumentException)
					{
					}
				}
				num2 += num;
			}
			GUILayout.Space(70f);
			GUILayout.EndVertical();
			GUILayout.EndScrollView();
		}

		private void AvatarMenuWindow(int id)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			avatarMenuWindowScrollPos = GUILayout.BeginScrollView(avatarMenuWindowScrollPos, false, true, Array.Empty<GUILayoutOption>());
			float y = avatarMenuWindowScrollPos.y;
			float height = ((Rect)(ref AvatarWindowRect)).height;
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			float num = 21f;
			float num2 = num;
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Automatic", Array.Empty<GUILayoutOption>());
			if (PluginConfig.selectedAvatar.Value == "")
			{
				GUI.enabled = false;
			}
			if (GUILayout.Button("Select", Array.Empty<GUILayoutOption>()))
			{
				((ConfigEntryBase)PluginConfig.selectedAvatar).BoxedValue = "";
			}
			GUI.enabled = true;
			GUILayout.EndHorizontal();
			foreach (string key in playerModelBundlePaths.Keys)
			{
				if (num == 0f || (num2 + num >= y && num2 <= y + height))
				{
					try
					{
						GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
						GUILayout.Label(key, Array.Empty<GUILayoutOption>());
						if (PlayerModel.localModel.selectedAvatar == key)
						{
							GUI.enabled = false;
						}
						if (GUILayout.Button("Select", Array.Empty<GUILayoutOption>()))
						{
							((ConfigEntryBase)PluginConfig.selectedAvatar).BoxedValue = key;
						}
						GUI.enabled = true;
						GUILayout.EndHorizontal();
					}
					catch (ArgumentException)
					{
					}
				}
				else
				{
					try
					{
						GUILayout.Space(num);
					}
					catch (ArgumentException)
					{
					}
				}
				num2 += num;
			}
			GUILayout.EndVertical();
			GUILayout.EndScrollView();
		}
	}
	public static class PluginConfig
	{
		public const string PLUGIN_GUID = "ValheimPlayerModels";

		public const string PLUGIN_NAME = "Valheim Player Models";

		public const string PLUGIN_VERSION = "1.0.1";

		public static ConfigFile config;

		public static ConfigEntry<bool> enablePlayerModels;

		public static ConfigEntry<bool> enableCustomRagdoll;

		public static ConfigEntry<string> serverUrl;

		public static ConfigEntry<string> selectedAvatar;

		public static ConfigEntry<KeyboardShortcut> reloadKey;

		public static ConfigEntry<KeyboardShortcut> actionMenuKey;

		public static ConfigEntry<KeyboardShortcut> avatarMenuKey;

		public static void InitConfig(ConfigFile _config)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Expected O, but got Unknown
			config = _config;
			enablePlayerModels = config.Bind<bool>("General", "EnablePlayerModels", true, new ConfigDescription("Toggle the use of custom player models.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1
				}
			}));
			enableCustomRagdoll = config.Bind<bool>("General", "EnableCustomRagdoll", true, new ConfigDescription("Toggle the use of custom player models for ragdolls.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 2
				}
			}));
			selectedAvatar = config.Bind<string>("General", "SelectedAvatar", "", new ConfigDescription("Selected avatar name, leave empty for automatic", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Browsable = false
				}
			}));
			reloadKey = config.Bind<KeyboardShortcut>("General", "ReloadKey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), new ConfigDescription("The key to reload the player models.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 3
				}
			}));
			actionMenuKey = config.Bind<KeyboardShortcut>("General", "ActionMenuKey", new KeyboardShortcut((KeyCode)103, Array.Empty<KeyCode>()), new ConfigDescription("The key to open the action menu.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 4
				}
			}));
			avatarMenuKey = config.Bind<KeyboardShortcut>("General", "AvatarMenuKey", new KeyboardShortcut((KeyCode)279, Array.Empty<KeyCode>()), new ConfigDescription("The key to open the avatar selection menu.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 4
				}
			}));
			serverUrl = config.Bind<string>("General", "ServerURL", "", new ConfigDescription("Player Models Server URL, keep empty for local player models only.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 6
				}
			}));
		}
	}
	[DefaultExecutionOrder(int.MaxValue)]
	public sealed class SpringBone : MonoBehaviour
	{
		public enum SpringBoneUpdateType
		{
			LateUpdate,
			FixedUpdate
		}

		private class SpringBoneLogic
		{
			private Transform m_transform;

			private Vector3 m_boneAxis;

			private Vector3 m_currentTail;

			private readonly float m_length;

			private Vector3 m_prevTail;

			public Transform Head => m_transform;

			public Vector3 Tail
			{
				get
				{
					//IL_0006: 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)
					//IL_000f: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					Matrix4x4 localToWorldMatrix = m_transform.localToWorldMatrix;
					return ((Matrix4x4)(ref localToWorldMatrix)).MultiplyPoint(m_boneAxis * m_length);
				}
			}

			private Quaternion LocalRotation { get; }

			private Quaternion ParentRotation => ((Object)(object)m_transform.parent != (Object)null) ? m_transform.parent.rotation : Quaternion.identity;

			public SpringBoneLogic(Transform center, Transform transform, Vector3 localChildPosition)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: 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_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				m_transform = transform;
				Vector3 val = m_transform.TransformPoint(localChildPosition);
				m_currentTail = (((Object)(object)center != (Object)null) ? center.InverseTransformPoint(val) : val);
				m_prevTail = m_currentTail;
				LocalRotation = transform.localRotation;
				m_boneAxis = ((Vector3)(ref localChildPosition)).normalized;
				m_length = ((Vector3)(ref localChildPosition)).magnitude;
			}

			public void Update(Transform center, float stiffnessForce, float dragForce, Vector3 external)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: 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)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_005d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_007f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0090: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Unknown result type (might be due to invalid IL or missing references)
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Unknown result type (might be due to invalid IL or missing references)
				//IL_00db: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val = (((Object)(object)center != (Object)null) ? center.TransformPoint(m_currentTail) : m_currentTail);
				Vector3 val2 = (((Object)(object)center != (Object)null) ? center.TransformPoint(m_prevTail) : m_prevTail);
				Vector3 val3 = val + (val - val2) * (1f - dragForce) + ParentRotation * LocalRotation * m_boneAxis * stiffnessForce + external;
				Vector3 position = m_transform.position;
				Vector3 val4 = val3 - position;
				val3 = position + ((Vector3)(ref val4)).normalized * m_length;
				m_prevTail = (((Object)(object)center != (Object)null) ? center.InverseTransformPoint(val) : val);
				m_currentTail = (((Object)(object)center != (Object)null) ? center.InverseTransformPoint(val3) : val3);
				m_transform.rotation = ApplyRotation(val3);
			}

			protected virtual Quaternion ApplyRotation(Vector3 nextTail)
			{
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: 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_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				Quaternion val = ParentRotation * LocalRotation;
				return Quaternion.FromToRotation(val * m_boneAxis, nextTail - m_transform.position) * val;
			}

			public void DrawGizmo(Transform center, Color color)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: 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)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_003c: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: 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_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: 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)
				Vector3 val = (((Object)(object)center != (Object)null) ? center.TransformPoint(m_currentTail) : m_currentTail);
				Vector3 val2 = (((Object)(object)center != (Object)null) ? center.TransformPoint(m_prevTail) : m_prevTail);
				Gizmos.color = Color.gray;
				Gizmos.DrawLine(val, val2);
				Gizmos.color = color;
				Gizmos.DrawLine(val, m_transform.position);
			}
		}

		[SerializeField]
		public string m_comment;

		[SerializeField]
		[Header("Gizmo")]
		private bool m_drawGizmo = false;

		[SerializeField]
		private Color m_gizmoColor = Color.yellow;

		[SerializeField]
		[Range(0f, 4f)]
		[Header("Settings")]
		public float m_stiffnessForce = 1f;

		[SerializeField]
		[Range(0f, 2f)]
		public float m_gravityPower;

		[SerializeField]
		public Vector3 m_gravityDir = new Vector3(0f, -1f, 0f);

		[SerializeField]
		[Range(0f, 1f)]
		public float m_dragForce = 0.4f;

		[SerializeField]
		public Transform m_center;

		[SerializeField]
		public List<Transform> RootBones = new List<Transform>();

		private Dictionary<Transform, Quaternion> m_initialLocalRotationMap;

		[SerializeField]
		public SpringBoneUpdateType m_updateType = SpringBoneUpdateType.LateUpdate;

		private List<SpringBoneLogic> m_verlet = new List<SpringBoneLogic>();

		private void Awake()
		{
			Setup();
		}

		[ContextMenu("Reset bones")]
		public void Setup(bool force = false)
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			if (RootBones == null)
			{
				return;
			}
			if (force || m_initialLocalRotationMap == null)
			{
				m_initialLocalRotationMap = new Dictionary<Transform, Quaternion>();
			}
			else
			{
				foreach (KeyValuePair<Transform, Quaternion> item in m_initialLocalRotationMap)
				{
					item.Key.localRotation = item.Value;
				}
				m_initialLocalRotationMap.Clear();
			}
			m_verlet.Clear();
			foreach (Transform rootBone in RootBones)
			{
				if ((Object)(object)rootBone != (Object)null)
				{
					Transform[] componentsInChildren = ((Component)((Component)rootBone).transform).GetComponentsInChildren<Transform>(true);
					foreach (Transform val in componentsInChildren)
					{
						m_initialLocalRotationMap[val] = val.localRotation;
					}
					SetupRecursive(m_center, rootBone);
				}
			}
		}

		private float GetUniformedLossyScale(Transform transform)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			return Mathf.Max(Mathf.Max(transform.lossyScale.x, transform.lossyScale.y), transform.lossyScale.z);
		}

		private static IEnumerable<Transform> GetChildren(Transform parent)
		{
			int i = 0;
			while (i < parent.childCount)
			{
				yield return parent.GetChild(i);
				int num = i + 1;
				i = num;
			}
		}

		private void SetupRecursive(Transform center, Transform parent)
		{
			//IL_0003: 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)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			Vector3 val = default(Vector3);
			Vector3 val2 = default(Vector3);
			if (parent.childCount == 0)
			{
				Vector3 val3 = parent.position - parent.parent.position;
				Vector3 val4 = parent.position + ((Vector3)(ref val3)).normalized * 0.07f * GetUniformedLossyScale(parent);
				Matrix4x4 worldToLocalMatrix = parent.worldToLocalMatrix;
				val = ((Matrix4x4)(ref worldToLocalMatrix)).MultiplyPoint(val4);
				val2 = parent.lossyScale;
			}
			else
			{
				Transform val5 = GetChildren(parent).First();
				val = val5.localPosition;
				val2 = val5.lossyScale;
			}
			m_verlet.Add(new SpringBoneLogic(center, parent, new Vector3(val.x * val2.x, val.y * val2.y, val.z * val2.z)));
			foreach (Transform item in parent)
			{
				Transform parent2 = item;
				SetupRecursive(center, parent2);
			}
		}

		private void LateUpdate()
		{
			if (m_updateType == SpringBoneUpdateType.LateUpdate)
			{
				UpdateProcess(Time.deltaTime);
			}
		}

		private void FixedUpdate()
		{
			if (m_updateType == SpringBoneUpdateType.FixedUpdate)
			{
				UpdateProcess(Time.fixedDeltaTime);
			}
		}

		private void UpdateProcess(float deltaTime)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			if (m_verlet == null || m_verlet.Count == 0)
			{
				if (RootBones == null)
				{
					return;
				}
				Setup();
			}
			float stiffnessForce = m_stiffnessForce * deltaTime;
			Vector3 external = m_gravityDir * (m_gravityPower * deltaTime);
			foreach (SpringBoneLogic item in m_verlet)
			{
				item.Update(m_center, stiffnessForce, m_dragForce, external);
			}
		}

		private void OnDrawGizmos()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!m_drawGizmo)
			{
				return;
			}
			foreach (SpringBoneLogic item in m_verlet)
			{
				item.DrawGizmo(m_center, m_gizmoColor);
			}
		}
	}
	public class ValheimToggleTracking : StateMachineBehaviour
	{
		public bool enableTracking = true;

		public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
		{
			PlayerModel component = ((Component)((Component)animator).transform.parent).GetComponent<PlayerModel>();
			if (Object.op_Implicit((Object)(object)component))
			{
				component.enableTracking = enableTracking;
			}
		}
	}
	public static class Utils
	{
		public static void Resize<T>(this List<T> list, int sz, T c)
		{
			int count = list.Count;
			if (sz < count)
			{
				list.RemoveRange(sz, count - sz);
			}
			else if (sz > count)
			{
				if (sz > list.Capacity)
				{
					list.Capacity = sz;
				}
				list.AddRange(Enumerable.Repeat(c, sz - count));
			}
		}

		public static void Resize<T>(this List<T> list, int sz) where T : new()
		{
			list.Resize(sz, new T());
		}
	}
	public enum ControlType
	{
		Button,
		Toggle,
		Slider
	}
	public class ValheimAvatarDescriptor : MonoBehaviour
	{
		public string avatarName = "player";

		public Transform leftHand;

		public Transform rightHand;

		public Transform helmet;

		public Transform backShield;

		public Transform backMelee;

		public Transform backTwohandedMelee;

		public Transform backBow;

		public Transform backTool;

		public Transform backAtgeir;

		public bool showHelmet;

		public bool showCape;

		public List<string> boolParameters;

		public List<bool> boolParametersDefault;

		public List<string> intParameters;

		public List<int> intParametersDefault;

		public List<string> floatParameters;

		public List<float> floatParametersDefault;

		public string[] controlName;

		public ControlType[] controlTypes;

		public string[] controlParameterNames;

		public float[] controlValues;

		private void Awake()
		{
			Validate();
		}

		public void Validate()
		{
			for (int i = 0; i < boolParameters.Count; i++)
			{
				if (!boolParameters[i].StartsWith("param_"))
				{
					boolParameters[i] = "param_" + boolParameters[i];
				}
			}
			for (int j = 0; j < intParameters.Count; j++)
			{
				if (!intParameters[j].StartsWith("param_"))
				{
					intParameters[j] = "param_" + intParameters[j];
				}
			}
			for (int k = 0; k < floatParameters.Count; k++)
			{
				if (!floatParameters[k].StartsWith("param_"))
				{
					floatParameters[k] = "param_" + floatParameters[k];
				}
			}
			if (boolParametersDefault.Count != boolParameters.Count)
			{
				boolParametersDefault.Resize(boolParameters.Count);
			}
			if (intParametersDefault.Count != intParameters.Count)
			{
				intParametersDefault.Resize(intParameters.Count);
			}
			if (floatParametersDefault.Count != floatParameters.Count)
			{
				floatParametersDefault.Resize(floatParameters.Count);
			}
			if (controlTypes.Length != controlName.Length)
			{
				Array.Resize(ref controlTypes, controlName.Length);
			}
			if (controlParameterNames.Length != controlName.Length)
			{
				Array.Resize(ref controlParameterNames, controlName.Length);
			}
			if (controlValues.Length != controlName.Length)
			{
				Array.Resize(ref controlValues, controlName.Length);
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ValheimPlayerModels";

		public const string PLUGIN_NAME = "Valheim Player Models";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ValheimPlayerModels.Loaders
{
	public class AvatarInstance
	{
		public enum ParameterType
		{
			Bool,
			Int,
			Float
		}

		public class AvatarParameter
		{
			public ParameterType type;

			public bool boolValue;

			public int intValue;

			public float floatValue;
		}

		public class MenuControl
		{
			public string name;

			public ControlType type;

			public string parameter;

			public float value;
		}

		private PlayerModel Owner;

		public GameObject AvatarObject;

		public Transform Transform;

		public Transform LeftFoot;

		public Transform RightFoot;

		public Transform Hips;

		public Animator Animator;

		public LODGroup lodGroup;

		public ValheimAvatarDescriptor AvatarDescriptor;

		public Dictionary<int, AvatarParameter> Parameters;

		public List<MenuControl> MenuControls;

		public AvatarInstance(PlayerModel owner)
		{
			Owner = owner;
		}

		public void SetParameterValue(string name, float value)
		{
			int hash = Animator.StringToHash(name);
			SetParameterValue(hash, value);
		}

		public void SetParameterValue(int hash, float value)
		{
			if (Parameters.ContainsKey(hash))
			{
				switch (Parameters[hash].type)
				{
				case ParameterType.Bool:
					SetBool(hash, value != 0f);
					break;
				case ParameterType.Int:
					SetInt(hash, (int)value);
					break;
				case ParameterType.Float:
					SetFloat(hash, value);
					break;
				default:
					throw new ArgumentOutOfRangeException();
				}
			}
		}

		public float GetParameterValue(string name)
		{
			int hash = Animator.StringToHash(name);
			return GetParameterValue(hash);
		}

		public float GetParameterValue(int hash)
		{
			if (!Parameters.ContainsKey(hash))
			{
				return 0f;
			}
			return Parameters[hash].type switch
			{
				ParameterType.Bool => Parameters[hash].boolValue ? 1 : 0, 
				ParameterType.Int => Parameters[hash].intValue, 
				ParameterType.Float => Parameters[hash].floatValue, 
				_ => throw new ArgumentOutOfRangeException(), 
			};
		}

		public bool SetBool(string name, bool value)
		{
			int hash = Animator.StringToHash(name);
			return SetBool(hash, value);
		}

		public bool SetBool(int hash, bool value)
		{
			if (!Parameters.ContainsKey(hash))
			{
				return false;
			}
			Parameters[hash].boolValue = value;
			Animator.SetBool(hash, value);
			if (Owner.zNetView.GetZDO() != null && Owner.zNetView.IsOwner())
			{
				Owner.zNetView.GetZDO().Set(438569 + hash, value);
			}
			return true;
		}

		public bool SetInt(string name, int value)
		{
			int hash = Animator.StringToHash(name);
			return SetInt(hash, value);
		}

		public bool SetInt(int hash, int value)
		{
			if (!Parameters.ContainsKey(hash))
			{
				return false;
			}
			Parameters[hash].intValue = value;
			Animator.SetInteger(hash, value);
			if (Owner.zNetView.GetZDO() != null && Owner.zNetView.IsOwner())
			{
				Owner.zNetView.GetZDO().Set(438569 + hash, value, false);
			}
			return true;
		}

		public bool SetFloat(string name, float value)
		{
			int hash = Animator.StringToHash(name);
			return SetFloat(hash, value);
		}

		public bool SetFloat(int hash, float value)
		{
			if (!Parameters.ContainsKey(hash))
			{
				return false;
			}
			Parameters[hash].floatValue = value;
			Animator.SetFloat(hash, value);
			if (Owner.zNetView.GetZDO() != null && Owner.zNetView.IsOwner())
			{
				Owner.zNetView.GetZDO().Set(438569 + hash, value);
			}
			return true;
		}
	}
	public abstract class AvatarLoaderBase
	{
		public bool LoadedSuccessfully { get; protected set; }

		public abstract IEnumerator LoadFile(string file);

		public abstract AvatarInstance LoadAvatar(PlayerModel playerModel);

		public abstract void Unload();
	}
	public class ValavtrLoader : AvatarLoaderBase
	{
		private AssetBundle avatarBundle;

		public override IEnumerator LoadFile(string file)
		{
			AssetBundleCreateRequest bundleRequest = AssetBundle.LoadFromFileAsync(file);
			yield return bundleRequest;
			avatarBundle = bundleRequest.assetBundle;
			if (!Object.op_Implicit((Object)(object)avatarBundle))
			{
				Plugin.Log.LogError((object)("Avatar Bundle " + file + " couldn't load!"));
				base.LoadedSuccessfully = false;
			}
			else
			{
				base.LoadedSuccessfully = true;
			}
		}

		public override AvatarInstance LoadAvatar(PlayerModel playerModel)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			AvatarInstance avatarInstance = new AvatarInstance(playerModel);
			GameObject val = avatarBundle.LoadAsset<GameObject>("_avatar");
			if (!Object.op_Implicit((Object)(object)val))
			{
				Plugin.Log.LogError((object)"Couldn't find avatar prefab");
				return null;
			}
			avatarInstance.AvatarObject = Object.Instantiate<GameObject>(val);
			avatarInstance.AvatarDescriptor = avatarInstance.AvatarObject.GetComponent<ValheimAvatarDescriptor>();
			avatarInstance.Animator = avatarInstance.AvatarObject.GetComponent<Animator>();
			avatarInstance.Transform = avatarInstance.AvatarObject.transform;
			avatarInstance.Transform.SetParent(((Component)playerModel).transform, false);
			avatarInstance.LeftFoot = avatarInstance.Animator.GetBoneTransform((HumanBodyBones)5);
			avatarInstance.RightFoot = avatarInstance.Animator.GetBoneTransform((HumanBodyBones)6);
			avatarInstance.Hips = avatarInstance.Animator.GetBoneTransform((HumanBodyBones)0);
			avatarInstance.lodGroup = avatarInstance.AvatarObject.AddComponent<LODGroup>();
			Renderer[] componentsInChildren = (Renderer[])(object)avatarInstance.AvatarObject.GetComponentsInChildren<SkinnedMeshRenderer>();
			LOD val2 = default(LOD);
			((LOD)(ref val2))..ctor(0.1f, componentsInChildren);
			avatarInstance.lodGroup.SetLODs((LOD[])(object)new LOD[1] { val2 });
			avatarInstance.lodGroup.RecalculateBounds();
			LODGroup component = ((Character)playerModel.player).GetVisual().GetComponent<LODGroup>();
			avatarInstance.lodGroup.fadeMode = component.fadeMode;
			avatarInstance.lodGroup.animateCrossFading = component.animateCrossFading;
			Renderer[] componentsInChildren2 = avatarInstance.AvatarObject.GetComponentsInChildren<Renderer>();
			Renderer[] array = componentsInChildren2;
			foreach (Renderer val3 in array)
			{
				Material[] sharedMaterials = val3.sharedMaterials;
				foreach (Material val4 in sharedMaterials)
				{
					if (Object.op_Implicit((Object)(object)val4) && ((Object)val4.shader).name == "Valheim/Standard")
					{
						val4.shader = Shader.Find("Custom/Player");
						Texture2D val5 = (Texture2D)(val4.HasProperty("_MainTex") ? /*isinst with value type is only supported in some contexts*/: null);
						Texture val6 = (val4.HasProperty("_BumpMap") ? val4.GetTexture("_BumpMap") : null);
						val4.SetTexture("_MainTex", (Texture)(object)val5);
						val4.SetTexture("_SkinBumpMap", val6);
						val4.SetTexture("_ChestTex", (Texture)(object)val5);
						val4.SetTexture("_ChestBumpMap", val6);
						val4.SetTexture("_LegsTex", (Texture)(object)val5);
						val4.SetTexture("_LegsBumpMap", val6);
					}
				}
			}
			avatarInstance.AvatarDescriptor.Validate();
			avatarInstance.Parameters = new Dictionary<int, AvatarInstance.AvatarParameter>();
			if (avatarInstance.AvatarDescriptor.boolParameters != null)
			{
				for (int k = 0; k < avatarInstance.AvatarDescriptor.boolParameters.Count; k++)
				{
					int num = Animator.StringToHash(avatarInstance.AvatarDescriptor.boolParameters[k]);
					if (!avatarInstance.Parameters.ContainsKey(num))
					{
						avatarInstance.Parameters.Add(num, new AvatarInstance.AvatarParameter
						{
							type = AvatarInstance.ParameterType.Bool,
							boolValue = avatarInstance.AvatarDescriptor.boolParametersDefault[k]
						});
						avatarInstance.Animator.SetBool(num, avatarInstance.AvatarDescriptor.boolParametersDefault[k]);
					}
				}
			}
			if (avatarInstance.AvatarDescriptor.intParameters != null)
			{
				for (int l = 0; l < avatarInstance.AvatarDescriptor.intParameters.Count; l++)
				{
					int num2 = Animator.StringToHash(avatarInstance.AvatarDescriptor.intParameters[l]);
					if (!avatarInstance.Parameters.ContainsKey(num2))
					{
						avatarInstance.Parameters.Add(num2, new AvatarInstance.AvatarParameter
						{
							type = AvatarInstance.ParameterType.Int,
							intValue = avatarInstance.AvatarDescriptor.intParametersDefault[l]
						});
						avatarInstance.Animator.SetInteger(num2, avatarInstance.AvatarDescriptor.intParametersDefault[l]);
					}
				}
			}
			if (avatarInstance.AvatarDescriptor.floatParameters != null)
			{
				for (int m = 0; m < avatarInstance.AvatarDescriptor.floatParameters.Count; m++)
				{
					int num3 = Animator.StringToHash(avatarInstance.AvatarDescriptor.floatParameters[m]);
					if (!avatarInstance.Parameters.ContainsKey(num3))
					{
						avatarInstance.Parameters.Add(num3, new AvatarInstance.AvatarParameter
						{
							type = AvatarInstance.ParameterType.Float,
							floatValue = avatarInstance.AvatarDescriptor.floatParametersDefault[m]
						});
						avatarInstance.Animator.SetFloat(num3, avatarInstance.AvatarDescriptor.floatParametersDefault[m]);
					}
				}
			}
			avatarInstance.MenuControls = new List<AvatarInstance.MenuControl>();
			if (avatarInstance.AvatarDescriptor.controlName != null)
			{
				for (int n = 0; n < avatarInstance.AvatarDescriptor.controlName.Length; n++)
				{
					avatarInstance.MenuControls.Add(new AvatarInstance.MenuControl
					{
						name = avatarInstance.AvatarDescriptor.controlName[n],
						type = avatarInstance.AvatarDescriptor.controlTypes[n],
						parameter = avatarInstance.AvatarDescriptor.controlParameterNames[n],
						value = avatarInstance.AvatarDescriptor.controlValues[n]
					});
				}
			}
			return avatarInstance;
		}

		public override void Unload()
		{
			if (Object.op_Implicit((Object)(object)avatarBundle))
			{
				avatarBundle.Unload(true);
			}
		}
	}
	public class VrmLoader : AvatarLoaderBase
	{
		public override IEnumerator LoadFile(string file)
		{
			base.LoadedSuccessfully = false;
			yield break;
		}

		public override AvatarInstance LoadAvatar(PlayerModel playerModel)
		{
			return null;
		}

		public override void Unload()
		{
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}