BepInEx/plugins/ttik/ttik.dll

Decompiled 8 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.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using FIMSpace;
using FIMSpace.BonesStimulation;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using Mirror.RemoteCalls;
using PiUtils.Assets;
using PiUtils.Debug;
using PiUtils.Util;
using RootMotion.FinalIK;
using TTIK.Ik;
using TTIK.Ik.FingerTracking;
using TTIK.Network;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ttik")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+df557c79742a743046ccd74a1fe11c2518e3a398")]
[assembly: AssemblyProduct("Techtonica Inverse Kinematics")]
[assembly: AssemblyTitle("ttik")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.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 TTIK
{
	public class ModConfig
	{
		private static ConfigEntry<bool> modEnabled;

		public static ConfigEntry<float> fingerSyncDeadzone;

		public static void Init(ConfigFile config)
		{
			modEnabled = config.Bind<bool>("General", "Enabled", true, "Enable mod");
			fingerSyncDeadzone = config.Bind<float>("Sync", "Finger Sync Deadzone", 0.01f, "Deadzone for finger sync. If the difference between the local and remote finger position is less than this value, the remote finger will be set to the local finger position.");
		}

		public static bool ModEnabled()
		{
			return modEnabled.Value;
		}
	}
	[BepInPlugin("de.xenira.ttik", "Techtonica Inverse Kinematics", "0.2.2")]
	public class TTIK : BaseUnityPlugin
	{
		private static PluginLogger Logger;

		private static AssetLoader assetLoader;

		public static GameObject ikPlayerPrefab;

		public static GameObject trackingTargetPrefab;

		public static string gameExePath = Process.GetCurrentProcess().MainModule.FileName;

		public static string gamePath = Path.GetDirectoryName(gameExePath);

		private void Awake()
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Expected O, but got Unknown
			Logger = PluginLogger.GetLogger<TTIK>();
			Logger.LogInfo("Loading plugin ttik version 0.2.2...");
			License.LogLicense(Logger, "xenira", "ttik", "0.2.2");
			((Object)this).hideFlags = (HideFlags)61;
			assetLoader = new AssetLoader(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "assets"));
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			if (!ModConfig.ModEnabled())
			{
				Logger.LogInfo("Mod is disabled, skipping...");
				return;
			}
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			((MonoBehaviour)this).StartCoroutine(registerPrefabs());
			Logger.LogInfo("Plugin ttik version 0.2.2 is loaded!");
		}

		private static IEnumerator registerPrefabs()
		{
			Logger.LogInfo("Registering dummy prefab...");
			AssetBundle obj = assetLoader.LoadBundle("mirror");
			ikPlayerPrefab = obj.LoadAsset<GameObject>("DummyPrefab.prefab");
			ikPlayerPrefab.AddComponent<NetworkIkPlayer>();
			((NetworkTransformBase)ikPlayerPrefab.AddComponent<NetworkTransform>()).clientAuthority = true;
			Guid guid = new Guid("1b739df5-1600-4a8a-ae21-d2db4304f77b");
			NetworkClient.RegisterPrefab(ikPlayerPrefab, guid);
			obj.Unload(false);
			trackingTargetPrefab = assetLoader.LoadBundle("mirror").LoadAsset<GameObject>("DummyPrefab.prefab");
			((NetworkTransformBase)trackingTargetPrefab.AddComponent<NetworkTransform>()).clientAuthority = true;
			Guid guid2 = new Guid("17305811-edd9-46f4-9080-d10c2e85fff7");
			NetworkClient.RegisterPrefab(trackingTargetPrefab, guid2);
			Logger.LogInfo("Dummy prefab registered!");
			yield return null;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "ttik";

		public const string PLUGIN_NAME = "Techtonica Inverse Kinematics";

		public const string PLUGIN_VERSION = "0.2.2";
	}
}
namespace TTIK.Patch
{
	[Harmony]
	public class NetworkedThirdPersonPatch
	{
		private static PluginLogger Logger = PluginLogger.GetLogger<NetworkedThirdPersonPatch>();

		[HarmonyPatch(typeof(NetworkedPlayer), "OnStartServer")]
		[HarmonyPostfix]
		public static void OnStartServerPatch(NetworkedPlayer __instance)
		{
			Logger.LogDebug($"Spawning NetworkIkPlayer... {__instance.connection.connectionId}");
			AsyncGameObject.Timeout((Action)delegate
			{
				//IL_005d: 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)
				Logger.LogDebug($"Delayed spawning NetworkIkPlayer for {__instance.connection.connectionId}");
				Logger.LogDebug($"NetId: {((NetworkBehaviour)__instance).netId}");
				GameObject obj = Object.Instantiate<GameObject>(TTIK.ikPlayerPrefab);
				obj.transform.localPosition = Vector3.zero;
				obj.transform.localRotation = Quaternion.identity;
				NetworkServer.Spawn(obj, __instance.connection);
			}, 5f);
		}
	}
}
namespace TTIK.Network
{
	public class NetworkIkPlayer : NetworkBehaviour
	{
		public enum TrackingType
		{
			ThreePt,
			[Obsolete("Six point tracking is not yet supported yet.")]
			SixPt,
			[Obsolete("Seven point tracking is not yet supported yet.")]
			SevenPt
		}

		public enum IkState : uint
		{
			Disabled,
			Initialized,
			Calibrating,
			Calibrated
		}

		private const ulong IK_STATE_MASK = 1uL;

		private const ulong HEAD_TARGET_MASK = 2uL;

		private const ulong LEFT_HAND_TARGET_MASK = 4uL;

		private const ulong RIGHT_HAND_TARGET_MASK = 8uL;

		private const ulong SCALE_MASK = 8uL;

		private const ulong PLAYER_NET_ID_MASK = 16uL;

		private const ulong LEFT_THUMB_CURL_MASK = 32uL;

		private const ulong LEFT_INDEX_CURL_MASK = 64uL;

		private const ulong LEFT_MIDDLE_CURL_MASK = 128uL;

		private const ulong LEFT_RING_CURL_MASK = 256uL;

		private const ulong LEFT_PINKY_CURL_MASK = 512uL;

		private const ulong RIGHT_THUMB_CURL_MASK = 1024uL;

		private const ulong RIGHT_INDEX_CURL_MASK = 2048uL;

		private const ulong RIGHT_MIDDLE_CURL_MASK = 4096uL;

		private const ulong RIGHT_RING_CURL_MASK = 8192uL;

		private const ulong RIGHT_PINKY_CURL_MASK = 16384uL;

		private static PluginLogger Logger = PluginLogger.GetLogger<NetworkIkPlayer>();

		public IkPlayer ikPlayer;

		public static NetworkIkPlayer localInstance;

		private NetworkedThirdPerson playerDisplay;

		public TrackingType trackingType;

		private IkState _ikState;

		private uint _headTargetNetId;

		private uint _leftHandTargetNetId;

		private uint _rightHandTargetNetId;

		private float _scale = 1f;

		private uint _playerNetId;

		private float _leftThumbCurl;

		private float _leftIndexCurl;

		private float _leftMiddleCurl;

		private float _leftRingCurl;

		private float _leftPinkyCurl;

		private float _rightThumbCurl;

		private float _rightIndexCurl;

		private float _rightMiddleCurl;

		private float _rightRingCurl;

		private float _rightPinkyCurl;

		public IkState NetworkIkState
		{
			get
			{
				return _ikState;
			}
			[param: In]
			set
			{
				if (((NetworkBehaviour)this).SyncVarEqual<IkState>(value, ref _ikState))
				{
					return;
				}
				Logger.LogTrace($"Set ikState to {value} (old: {_ikState})");
				IkState ikState = _ikState;
				((NetworkBehaviour)this).SetSyncVar<IkState>(value, ref _ikState, 1uL);
				if (((NetworkBehaviour)this).getSyncVarHookGuard(1uL))
				{
					return;
				}
				((NetworkBehaviour)this).setSyncVarHookGuard(1uL, true);
				try
				{
					OnIkStateChanged(ikState, value);
				}
				catch (Exception)
				{
					Logger.LogError("Error invoking OnIkStateChanged event.");
				}
				finally
				{
					((NetworkBehaviour)this).setSyncVarHookGuard(1uL, false);
				}
			}
		}

		public uint NetworkHeadTargetNetId
		{
			get
			{
				return _headTargetNetId;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<uint>(value, ref _headTargetNetId))
				{
					((NetworkBehaviour)this).SetSyncVar<uint>(value, ref _headTargetNetId, 2uL);
				}
			}
		}

		public uint NetworkLeftHandTargetNetId
		{
			get
			{
				return _leftHandTargetNetId;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<uint>(value, ref _leftHandTargetNetId))
				{
					((NetworkBehaviour)this).SetSyncVar<uint>(value, ref _leftHandTargetNetId, 4uL);
				}
			}
		}

		public uint NetworkRightHandTargetNetId
		{
			get
			{
				return _rightHandTargetNetId;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<uint>(value, ref _rightHandTargetNetId))
				{
					((NetworkBehaviour)this).SetSyncVar<uint>(value, ref _rightHandTargetNetId, 8uL);
				}
			}
		}

		public float NetworkScale
		{
			get
			{
				return _scale;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _scale))
				{
					float scale = _scale;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _scale, 8uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(8uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(8uL, true);
						OnScaleChanged(scale, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(8uL, false);
					}
				}
			}
		}

		public uint NetworkplayerNetId
		{
			get
			{
				return _playerNetId;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<uint>(value, ref _playerNetId))
				{
					((NetworkBehaviour)this).SetSyncVar<uint>(value, ref _playerNetId, 16uL);
				}
			}
		}

		public float NetworkLeftThumbCurl
		{
			get
			{
				return _leftThumbCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _leftThumbCurl))
				{
					_ = _leftThumbCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _leftThumbCurl, 32uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(32uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(32uL, true);
						OnFingerCurlChange(HandType.Left, FingerType.Thumb, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(32uL, false);
					}
				}
			}
		}

		public float NetworkLeftIndexCurl
		{
			get
			{
				return _leftIndexCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _leftIndexCurl))
				{
					_ = _leftIndexCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _leftIndexCurl, 64uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(64uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(64uL, true);
						OnFingerCurlChange(HandType.Left, FingerType.Index, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(64uL, false);
					}
				}
			}
		}

		public float NetworkLeftMiddleCurl
		{
			get
			{
				return _leftMiddleCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _leftMiddleCurl))
				{
					_ = _leftMiddleCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _leftMiddleCurl, 128uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(128uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(128uL, true);
						OnFingerCurlChange(HandType.Left, FingerType.Middle, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(128uL, false);
					}
				}
			}
		}

		public float NetworkLeftRingCurl
		{
			get
			{
				return _leftRingCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _leftRingCurl))
				{
					_ = _leftRingCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _leftRingCurl, 256uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(256uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(256uL, true);
						OnFingerCurlChange(HandType.Left, FingerType.Ring, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(256uL, false);
					}
				}
			}
		}

		public float NetworkLeftPinkyCurl
		{
			get
			{
				return _leftPinkyCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _leftPinkyCurl))
				{
					_ = _leftPinkyCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _leftPinkyCurl, 512uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(512uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(512uL, true);
						OnFingerCurlChange(HandType.Left, FingerType.Pinky, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(512uL, false);
					}
				}
			}
		}

		public float NetworkRightThumbCurl
		{
			get
			{
				return _rightThumbCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _rightThumbCurl))
				{
					_ = _rightThumbCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _rightThumbCurl, 1024uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(1024uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(1024uL, true);
						OnFingerCurlChange(HandType.Right, FingerType.Thumb, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(1024uL, false);
					}
				}
			}
		}

		public float NetworkRightIndexCurl
		{
			get
			{
				return _rightIndexCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _rightIndexCurl))
				{
					_ = _rightIndexCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _rightIndexCurl, 2048uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(2048uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(2048uL, true);
						OnFingerCurlChange(HandType.Right, FingerType.Index, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(2048uL, false);
					}
				}
			}
		}

		public float NetworkRightMiddleCurl
		{
			get
			{
				return _rightMiddleCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _rightMiddleCurl))
				{
					_ = _rightMiddleCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _rightMiddleCurl, 4096uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(4096uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(4096uL, true);
						OnFingerCurlChange(HandType.Right, FingerType.Middle, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(4096uL, false);
					}
				}
			}
		}

		public float NetworkRightRingCurl
		{
			get
			{
				return _rightRingCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _rightRingCurl))
				{
					_ = _rightRingCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _rightRingCurl, 8192uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(8192uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(8192uL, true);
						OnFingerCurlChange(HandType.Right, FingerType.Ring, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(8192uL, false);
					}
				}
			}
		}

		public float NetworkRightPinkyCurl
		{
			get
			{
				return _rightPinkyCurl;
			}
			[param: In]
			set
			{
				if (!((NetworkBehaviour)this).SyncVarEqual<float>(value, ref _rightPinkyCurl))
				{
					_ = _rightPinkyCurl;
					((NetworkBehaviour)this).SetSyncVar<float>(value, ref _rightPinkyCurl, 16384uL);
					if (!((NetworkBehaviour)this).getSyncVarHookGuard(16384uL))
					{
						((NetworkBehaviour)this).setSyncVarHookGuard(16384uL, true);
						OnFingerCurlChange(HandType.Right, FingerType.Pinky, value);
						((NetworkBehaviour)this).setSyncVarHookGuard(16384uL, false);
					}
				}
			}
		}

		public static event Action<NetworkIkPlayer> OnLocalPlayerInitialized;

		public static event Action<IkPlayer> OnIkInitialized;

		public NetworkIkPlayer()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Expected O, but got Unknown
			RemoteCallHelper.RegisterCommandDelegate(typeof(NetworkIkPlayer), "CmdInitIkPlayer", new CmdDelegate(InvokeUserCode_CmdInitIkPlayer), true);
			RemoteCallHelper.RegisterCommandDelegate(typeof(NetworkIkPlayer), "CmdStartCalibration", new CmdDelegate(InvokeUserCode_CmdStartCalibration), true);
			RemoteCallHelper.RegisterCommandDelegate(typeof(NetworkIkPlayer), "CmdFinishCalibration", new CmdDelegate(InvokeUserCode_CmdFinishCalibration), true);
			RemoteCallHelper.RegisterCommandDelegate(typeof(NetworkIkPlayer), "CmdSetScale", new CmdDelegate(InvokeUserCode_CmdSetScale), true);
			RemoteCallHelper.RegisterCommandDelegate(typeof(NetworkIkPlayer), "CmdSetFingerCurl", new CmdDelegate(InvokeUserCode_CmdSetFingerCurl), true);
			RemoteCallHelper.RegisterRpcDelegate(typeof(NetworkIkPlayer), "RpcInitIk", new CmdDelegate(InvokeUserCode_RpcInitIk));
		}

		protected override bool SerializeSyncVars(NetworkWriter writer, bool forceAll)
		{
			bool result = ((NetworkBehaviour)this).SerializeSyncVars(writer, forceAll);
			if (forceAll)
			{
				NetworkWriterExtensions.WriteULong(writer, ulong.MaxValue);
				NetworkWriterExtensions.WriteUInt(writer, (uint)_ikState);
				NetworkWriterExtensions.WriteUInt(writer, _headTargetNetId);
				NetworkWriterExtensions.WriteUInt(writer, _leftHandTargetNetId);
				NetworkWriterExtensions.WriteUInt(writer, _rightHandTargetNetId);
				NetworkWriterExtensions.WriteFloat(writer, _scale);
				NetworkWriterExtensions.WriteUInt(writer, NetworkplayerNetId);
				NetworkWriterExtensions.WriteFloat(writer, _leftThumbCurl);
				NetworkWriterExtensions.WriteFloat(writer, _leftIndexCurl);
				NetworkWriterExtensions.WriteFloat(writer, _leftMiddleCurl);
				NetworkWriterExtensions.WriteFloat(writer, _leftRingCurl);
				NetworkWriterExtensions.WriteFloat(writer, _leftPinkyCurl);
				NetworkWriterExtensions.WriteFloat(writer, _rightThumbCurl);
				NetworkWriterExtensions.WriteFloat(writer, _rightIndexCurl);
				NetworkWriterExtensions.WriteFloat(writer, _rightMiddleCurl);
				NetworkWriterExtensions.WriteFloat(writer, _rightRingCurl);
				NetworkWriterExtensions.WriteFloat(writer, _rightPinkyCurl);
				return true;
			}
			ulong syncVarDirtyBits = ((NetworkBehaviour)this).syncVarDirtyBits;
			NetworkWriterExtensions.WriteULong(writer, syncVarDirtyBits);
			if ((syncVarDirtyBits & 1) != 0L)
			{
				NetworkWriterExtensions.WriteUInt(writer, (uint)_ikState);
				result = true;
			}
			if ((syncVarDirtyBits & 2) != 0L)
			{
				NetworkWriterExtensions.WriteUInt(writer, _headTargetNetId);
				result = true;
			}
			if ((syncVarDirtyBits & 4) != 0L)
			{
				NetworkWriterExtensions.WriteUInt(writer, _leftHandTargetNetId);
				result = true;
			}
			if ((syncVarDirtyBits & 8) != 0L)
			{
				NetworkWriterExtensions.WriteUInt(writer, _rightHandTargetNetId);
				result = true;
			}
			if ((syncVarDirtyBits & 8) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _scale);
				result = true;
			}
			if ((syncVarDirtyBits & 0x10) != 0L)
			{
				NetworkWriterExtensions.WriteUInt(writer, _playerNetId);
				result = true;
			}
			if ((syncVarDirtyBits & 0x20) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _leftThumbCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x40) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _leftIndexCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x80) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _leftMiddleCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x100) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _leftRingCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x200) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _leftPinkyCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x400) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _rightThumbCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x800) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _rightIndexCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x1000) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _rightMiddleCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x2000) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _rightRingCurl);
				result = true;
			}
			if ((syncVarDirtyBits & 0x4000) != 0L)
			{
				NetworkWriterExtensions.WriteFloat(writer, _rightPinkyCurl);
				result = true;
			}
			return result;
		}

		protected override void DeserializeSyncVars(NetworkReader reader, bool initialState)
		{
			((NetworkBehaviour)this).DeserializeSyncVars(reader, initialState);
			ulong num = NetworkReaderExtensions.ReadULong(reader);
			Logger.LogDebug("Deserializing sync vars: " + Convert.ToString((long)num, 2));
			if ((num & 1) != 0L)
			{
				Logger.LogDebug("Deserializing ikState...");
				NetworkIkState = (IkState)NetworkReaderExtensions.ReadUInt(reader);
				Logger.LogDebug($"Deserialized ikState: {NetworkIkState}");
			}
			if ((num & 2) != 0L)
			{
				Logger.LogDebug("Deserializing headTargetNetId...");
				NetworkHeadTargetNetId = NetworkReaderExtensions.ReadUInt(reader);
				Logger.LogDebug($"Deserialized headTargetNetId: {NetworkHeadTargetNetId}");
			}
			if ((num & 4) != 0L)
			{
				Logger.LogDebug("Deserializing leftHandTargetNetId...");
				NetworkLeftHandTargetNetId = NetworkReaderExtensions.ReadUInt(reader);
				Logger.LogDebug($"Deserialized leftHandTargetNetId: {NetworkLeftHandTargetNetId}");
			}
			if ((num & 8) != 0L)
			{
				Logger.LogDebug("Deserializing rightHandTargetNetId...");
				NetworkRightHandTargetNetId = NetworkReaderExtensions.ReadUInt(reader);
				Logger.LogDebug($"Deserialized rightHandTargetNetId: {NetworkRightHandTargetNetId}");
			}
			if ((num & 8) != 0L)
			{
				Logger.LogDebug("Deserializing scale...");
				NetworkScale = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogDebug($"Deserialized scale: {NetworkScale}");
			}
			if ((num & 0x10) != 0L)
			{
				Logger.LogDebug("Deserializing playerNetId...");
				NetworkplayerNetId = NetworkReaderExtensions.ReadUInt(reader);
				Logger.LogDebug($"Deserialized playerNetId: {NetworkplayerNetId}");
			}
			if ((num & 0x20) != 0L)
			{
				Logger.LogTrace("Deserializing leftThumbCurl...");
				NetworkLeftThumbCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized leftThumbCurl: {NetworkLeftThumbCurl}");
			}
			if ((num & 0x40) != 0L)
			{
				Logger.LogTrace("Deserializing leftIndexCurl...");
				NetworkLeftIndexCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized leftIndexCurl: {NetworkLeftIndexCurl}");
			}
			if ((num & 0x80) != 0L)
			{
				Logger.LogTrace("Deserializing leftMiddleCurl...");
				NetworkLeftMiddleCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized leftMiddleCurl: {NetworkLeftMiddleCurl}");
			}
			if ((num & 0x100) != 0L)
			{
				Logger.LogTrace("Deserializing leftRingCurl...");
				NetworkLeftRingCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized leftRingCurl: {NetworkLeftRingCurl}");
			}
			if ((num & 0x200) != 0L)
			{
				Logger.LogTrace("Deserializing leftPinkyCurl...");
				NetworkLeftPinkyCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized leftPinkyCurl: {NetworkLeftPinkyCurl}");
			}
			if ((num & 0x400) != 0L)
			{
				Logger.LogTrace("Deserializing rightThumbCurl...");
				NetworkRightThumbCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized rightThumbCurl: {NetworkRightThumbCurl}");
			}
			if ((num & 0x800) != 0L)
			{
				Logger.LogTrace("Deserializing rightIndexCurl...");
				NetworkRightIndexCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized rightIndexCurl: {NetworkRightIndexCurl}");
			}
			if ((num & 0x1000) != 0L)
			{
				Logger.LogTrace("Deserializing rightMiddleCurl...");
				NetworkRightMiddleCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized rightMiddleCurl: {NetworkRightMiddleCurl}");
			}
			if ((num & 0x2000) != 0L)
			{
				Logger.LogTrace("Deserializing rightRingCurl...");
				NetworkRightRingCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized rightRingCurl: {NetworkRightRingCurl}");
			}
			if ((num & 0x4000) != 0L)
			{
				Logger.LogTrace("Deserializing rightPinkyCurl...");
				NetworkRightPinkyCurl = NetworkReaderExtensions.ReadFloat(reader);
				Logger.LogTrace($"Deserialized rightPinkyCurl: {NetworkRightPinkyCurl}");
			}
		}

		public void CmdInitIkPlayer()
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			((NetworkBehaviour)this).SendCommandInternal(typeof(NetworkIkPlayer), "CmdInitIkPlayer", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_CmdInitIkPlayer(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("Command CmdInitIkPlayer called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_CmdInitIkPlayer();
			}
		}

		protected void UserCode_CmdInitIkPlayer()
		{
			Logger.LogDebug("[Command] Initializing IkPlayer...");
			if (trackingType == TrackingType.SixPt)
			{
				Logger.LogError("Six point tracking is not supported yet.");
				throw new NotImplementedException();
			}
			uint netId = ((NetworkBehaviour)this).connectionToClient.identity.netId;
			GameObject val = spawnTarget($"{netId} head target");
			GameObject val2 = spawnTarget($"{netId} left hand target");
			GameObject val3 = spawnTarget($"{netId} right hand target");
			NetworkHeadTargetNetId = val.GetComponent<NetworkIdentity>().netId;
			NetworkLeftHandTargetNetId = val2.GetComponent<NetworkIdentity>().netId;
			NetworkRightHandTargetNetId = val3.GetComponent<NetworkIdentity>().netId;
			NetworkIkState = IkState.Initialized;
			if (trackingType == TrackingType.ThreePt)
			{
				RpcInitIk();
				return;
			}
			Logger.LogError($"Unknown / Unsupported tracking type {trackingType}.");
			throw new NotImplementedException();
		}

		public void CmdStartCalibration()
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			((NetworkBehaviour)this).SendCommandInternal(typeof(NetworkIkPlayer), "CmdStartCalibration", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_CmdStartCalibration(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("Command CmdStartCalibration called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_CmdStartCalibration();
			}
		}

		[Command]
		public void UserCode_CmdStartCalibration()
		{
			Logger.LogDebug("[Command] Starting calibration...");
			NetworkIkState = IkState.Calibrating;
		}

		public void CmdFinishCalibration(float scale)
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			NetworkWriterExtensions.WriteFloat((NetworkWriter)(object)writer, scale);
			((NetworkBehaviour)this).SendCommandInternal(typeof(NetworkIkPlayer), "CmdFinishCalibration", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_CmdFinishCalibration(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("Command CmdFinishCalibration called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_CmdFinishCalibration(NetworkReaderExtensions.ReadFloat(reader));
			}
		}

		[Command]
		public void UserCode_CmdFinishCalibration(float scale)
		{
			Logger.LogDebug("[Command] Finishing calibration...");
			NetworkScale = scale;
			NetworkIkState = IkState.Calibrated;
		}

		public void CmdSetScale(float scale)
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			NetworkWriterExtensions.WriteFloat((NetworkWriter)(object)writer, scale);
			((NetworkBehaviour)this).SendCommandInternal(typeof(NetworkIkPlayer), "CmdSetScale", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_CmdSetScale(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("Command CmdSetScale called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_CmdSetScale(NetworkReaderExtensions.ReadFloat(reader));
			}
		}

		[Command]
		public void UserCode_CmdSetScale(float scale)
		{
			Logger.LogDebug($"[Command] Setting scale to {scale}...");
			NetworkScale = scale;
		}

		public void CmdSetFingerCurl(HandType hand, FingerType finger, float value)
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)writer, (uint)hand);
			NetworkWriterExtensions.WriteUInt((NetworkWriter)(object)writer, (uint)finger);
			NetworkWriterExtensions.WriteFloat((NetworkWriter)(object)writer, value);
			((NetworkBehaviour)this).SendCommandInternal(typeof(NetworkIkPlayer), "CmdSetFingerCurl", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_CmdSetFingerCurl(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("Command CmdSetFingerCurl called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_CmdSetFingerCurl((HandType)NetworkReaderExtensions.ReadUInt(reader), (FingerType)NetworkReaderExtensions.ReadUInt(reader), NetworkReaderExtensions.ReadFloat(reader));
			}
		}

		[Command]
		public void UserCode_CmdSetFingerCurl(HandType hand, FingerType finger, float value)
		{
			Logger.LogTrace($"[Command] Setting {hand} {finger} curl to {value}...");
			switch (hand)
			{
			case HandType.Left:
				switch (finger)
				{
				case FingerType.Thumb:
					NetworkLeftThumbCurl = value;
					break;
				case FingerType.Index:
					NetworkLeftIndexCurl = value;
					break;
				case FingerType.Middle:
					NetworkLeftMiddleCurl = value;
					break;
				case FingerType.Ring:
					NetworkLeftRingCurl = value;
					break;
				case FingerType.Pinky:
					NetworkLeftPinkyCurl = value;
					break;
				default:
					Logger.LogError($"Unknown / Unsupported finger type {finger}.");
					break;
				}
				break;
			case HandType.Right:
				switch (finger)
				{
				case FingerType.Thumb:
					NetworkRightThumbCurl = value;
					break;
				case FingerType.Index:
					NetworkRightIndexCurl = value;
					break;
				case FingerType.Middle:
					NetworkRightMiddleCurl = value;
					break;
				case FingerType.Ring:
					NetworkRightRingCurl = value;
					break;
				case FingerType.Pinky:
					NetworkRightPinkyCurl = value;
					break;
				default:
					Logger.LogError($"Unknown / Unsupported finger type {finger}.");
					break;
				}
				break;
			default:
				Logger.LogError($"Unknown / Unsupported hand type {hand}.");
				break;
			}
		}

		public void RpcInitIk()
		{
			PooledNetworkWriter writer = NetworkWriterPool.GetWriter();
			((NetworkBehaviour)this).SendRPCInternal(typeof(NetworkIkPlayer), "RpcInitIk", (NetworkWriter)(object)writer, 0, true);
			NetworkWriterPool.Recycle(writer);
		}

		protected static void InvokeUserCode_RpcInitIk(NetworkBehaviour obj, NetworkReader reader, NetworkConnectionToClient senderConnection)
		{
			if (!NetworkClient.active)
			{
				Logger.LogError("ClientRPC RpcInitIk called on server.");
			}
			else
			{
				((NetworkIkPlayer)(object)obj).UserCode_RpcInitIk();
			}
		}

		private void UserCode_RpcInitIk()
		{
			AsyncGameObject.DelayUntil((Action)delegate
			{
				if (((NetworkBehaviour)this).hasAuthority)
				{
					NetworkIkPlayer.OnIkInitialized?.Invoke(ikPlayer);
					ikPlayer.OnCalibrating += CmdStartCalibration;
					ikPlayer.OnCalibrated += delegate
					{
						CmdFinishCalibration(ikPlayer.scale.GetValueOrDefault(1f));
					};
				}
			}, (Func<bool>)(() => (Object)(object)GetIkPlayer() != (Object)null));
		}

		private void OnIkStateChanged(IkState oldState, IkState newState)
		{
			Logger.LogDebug($"OnIkStateChanged: {oldState} -> {newState}");
			if (((NetworkBehaviour)this).hasAuthority)
			{
				return;
			}
			switch (NetworkIkState)
			{
			case IkState.Disabled:
				if ((Object)(object)ikPlayer != (Object)null)
				{
					Object.Destroy((Object)(object)ikPlayer);
				}
				break;
			case IkState.Calibrating:
				AsyncGameObject.DelayUntil((Action)delegate
				{
					GetIkPlayer().calibrate();
				}, (Func<bool>)(() => (Object)(object)GetIkPlayer() != (Object)null));
				break;
			case IkState.Calibrated:
				AsyncGameObject.DelayUntil((Action)delegate
				{
					IkPlayer ikPlayer = GetIkPlayer();
					if (oldState != IkState.Calibrating)
					{
						ikPlayer.calibrate();
					}
					ikPlayer.calibrated(NetworkScale);
					SetPlayerDisplay(enabled: false);
				}, (Func<bool>)(() => (Object)(object)GetIkPlayer() != (Object)null));
				break;
			default:
				Logger.LogError("Unknown / Unsupported IkState.");
				break;
			case IkState.Initialized:
				break;
			}
		}

		public IkPlayer GetIkPlayer()
		{
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			if ((Object)(object)ikPlayer != (Object)null)
			{
				return ikPlayer;
			}
			if (NetworkHeadTargetNetId == 0 || NetworkLeftHandTargetNetId == 0 || NetworkRightHandTargetNetId == 0)
			{
				Logger.LogError("Tracker data is not set.");
				return null;
			}
			NetworkedPlayer val = (from p in Object.FindObjectsOfType<NetworkedPlayer>()
				where ((NetworkBehaviour)p).netId == NetworkplayerNetId
				select p).FirstOrDefault();
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogError(string.Format("Player {0} not found in {1}", NetworkplayerNetId, GameState.instance.allPlayers.Keys.Aggregate((string a, string b) => a + ", " + b)));
				return null;
			}
			playerDisplay = val.display;
			val = (from p in GameState.instance.allPlayers
				where p.Key == NetworkplayerNetId.ToString()
				select p.Value).FirstOrDefault();
			GameObject gameObjectFromNetId = getGameObjectFromNetId(NetworkHeadTargetNetId);
			if ((Object)(object)gameObjectFromNetId == (Object)null)
			{
				Logger.LogWarning("Head target not found.");
				return null;
			}
			GameObject gameObjectFromNetId2 = getGameObjectFromNetId(NetworkLeftHandTargetNetId);
			if ((Object)(object)gameObjectFromNetId2 == (Object)null)
			{
				Logger.LogWarning("Left hand target not found.");
				return null;
			}
			GameObject gameObjectFromNetId3 = getGameObjectFromNetId(NetworkRightHandTargetNetId);
			if ((Object)(object)gameObjectFromNetId3 == (Object)null)
			{
				Logger.LogWarning("Right hand target not found.");
				return null;
			}
			if (((NetworkBehaviour)this).hasAuthority)
			{
				TrackingTarget headTarget = FHG_Utils.AddComponent<TrackingTarget>(new GameObject("Head Target"), new TrackingTarget(gameObjectFromNetId));
				TrackingTarget leftHandTarget = FHG_Utils.AddComponent<TrackingTarget>(new GameObject("Left Hand Target"), new TrackingTarget(gameObjectFromNetId2));
				TrackingTarget rightHandTarget = FHG_Utils.AddComponent<TrackingTarget>(new GameObject("Right Hand Target"), new TrackingTarget(gameObjectFromNetId3));
				ikPlayer = FHG_Utils.AddComponent<IkPlayer>(((Component)this).gameObject, new IkPlayer(headTarget, leftHandTarget, rightHandTarget));
				ikPlayer.OnScaleChanged += Callbacks.Unique<float>(Callbacks.Debounce<float>((Action<float>)CmdSetScale, 0.5f));
			}
			else
			{
				ikPlayer = FHG_Utils.AddComponent<IkPlayer>(((Component)this).gameObject, new IkPlayer(gameObjectFromNetId.transform, gameObjectFromNetId2.transform, gameObjectFromNetId3.transform));
			}
			Logger.LogDebug("IkPlayer initialized");
			return ikPlayer;
		}

		private void OnScaleChanged(float oldValue, float newValue)
		{
			Logger.LogDebug($"OnScaleChanged: {NetworkScale}");
			if (((NetworkBehaviour)this).hasAuthority)
			{
				return;
			}
			if (NetworkIkState == IkState.Calibrated)
			{
				AsyncGameObject.DelayUntil((Action)delegate
				{
					GetIkPlayer().setScale(NetworkScale);
				}, (Func<bool>)(() => (Object)(object)GetIkPlayer()?.ik != (Object)null));
			}
			else
			{
				IkPlayer ikPlayer = GetIkPlayer();
				if ((Object)(object)ikPlayer?.ik == (Object)null)
				{
					Logger.LogError("Scale was changed without an IkPlayer. This should not happen.");
				}
				else
				{
					ikPlayer.setScale(NetworkScale);
				}
			}
		}

		private void OnFingerCurlChange(HandType hand, FingerType finger, float newValue)
		{
			Logger.LogTrace($"OnFingerCurlChange: {hand} {finger} {newValue}");
			if (!((NetworkBehaviour)this).hasAuthority)
			{
				IkPlayer ikPlayer = GetIkPlayer();
				if ((Object)(object)ikPlayer == (Object)null)
				{
					Logger.LogError("Finger curl was changed without an IkPlayer. This should not happen.");
				}
				else
				{
					ikPlayer.UpdateFingerCurl(hand, finger, newValue);
				}
			}
		}

		public override void OnStartServer()
		{
			((NetworkBehaviour)this).OnStartServer();
			Logger.LogDebug($"OnStartServer {((NetworkBehaviour)this).connectionToClient.identity.netId}");
			NetworkplayerNetId = ((NetworkBehaviour)this).connectionToClient.identity.netId;
		}

		public override void OnStartAuthority()
		{
			((NetworkBehaviour)this).OnStartAuthority();
			Logger.LogDebug("OnStartAuthority");
			localInstance = this;
			NetworkIkPlayer.OnLocalPlayerInitialized?.Invoke(this);
		}

		public void UpdateFingerCurl(HandType hand, FingerType finger, float curl)
		{
			if (Mathf.Abs(GetFingerCurl(hand, finger) - curl) > ModConfig.fingerSyncDeadzone.Value)
			{
				CmdSetFingerCurl(hand, finger, curl);
			}
			if (((NetworkBehaviour)this).hasAuthority)
			{
				GetIkPlayer()?.UpdateFingerCurl(hand, finger, curl);
			}
		}

		private float GetFingerCurl(HandType hand, FingerType finger)
		{
			switch (finger)
			{
			case FingerType.Thumb:
				switch (hand)
				{
				case HandType.Left:
					return NetworkLeftThumbCurl;
				case HandType.Right:
					return NetworkRightThumbCurl;
				}
				break;
			case FingerType.Index:
				switch (hand)
				{
				case HandType.Left:
					return NetworkLeftIndexCurl;
				case HandType.Right:
					return NetworkRightIndexCurl;
				}
				break;
			case FingerType.Middle:
				switch (hand)
				{
				case HandType.Left:
					return NetworkLeftMiddleCurl;
				case HandType.Right:
					return NetworkRightMiddleCurl;
				}
				break;
			case FingerType.Ring:
				switch (hand)
				{
				case HandType.Left:
					return NetworkLeftRingCurl;
				case HandType.Right:
					return NetworkRightRingCurl;
				}
				break;
			case FingerType.Pinky:
				switch (hand)
				{
				case HandType.Left:
					return NetworkLeftPinkyCurl;
				case HandType.Right:
					return NetworkRightPinkyCurl;
				}
				break;
			}
			return 0f;
		}

		public void Update()
		{
			//IL_0019: 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_0032: Unknown result type (might be due to invalid IL or missing references)
			if (((NetworkBehaviour)this).hasAuthority)
			{
				((Component)this).transform.position = ((Component)Player._instance).transform.position + new Vector3(0f, 0f, -0.15f);
			}
		}

		private GameObject spawnTarget(string name)
		{
			Logger.LogDebug("Spawning target " + name + "...");
			GameObject obj = Object.Instantiate<GameObject>(TTIK.trackingTargetPrefab);
			((Object)obj).name = name;
			NetworkServer.Spawn(obj, ((NetworkBehaviour)this).connectionToClient);
			return obj;
		}

		private GameObject getGameObjectFromNetId(uint netId)
		{
			NetworkIdentity? obj = (from ni in Object.FindObjectsOfType<NetworkIdentity>()
				where ni.netId == netId
				select ni).FirstOrDefault();
			if (obj == null)
			{
				return null;
			}
			return ((Component)obj).gameObject;
		}

		private void SetPlayerDisplay(bool enabled)
		{
			GameObjectFinder.FindChildObjectByName("Ground Breaker", ((Component)playerDisplay).gameObject).SetActive(enabled);
		}
	}
}
namespace TTIK.Ik
{
	public class IkPlayer : MonoBehaviour
	{
		public enum TrackingTargetType
		{
			Head,
			LeftHand,
			RightHand
		}

		private static PluginLogger Logger = PluginLogger.GetLogger<IkPlayer>();

		public GameObject avatar;

		public VRIK ik;

		private float avatarHeight;

		private Dictionary<TrackingTargetType, TrackingTarget> trackingTargets = new Dictionary<TrackingTargetType, TrackingTarget>();

		private Transform head;

		public Transform headTarget;

		public Transform headTargetParent;

		public Transform leftHand;

		public Transform leftHandTarget;

		internal CustomHandUpdater leftHandFingers;

		public Transform rightHand;

		public Transform rightHandTarget;

		internal CustomHandUpdater rightHandFingers;

		private static References references;

		public bool? calibrating;

		public float? scale { get; private set; }

		public event Action<float> OnScaleChanged;

		public event Action OnCalibrating;

		public event Action OnCalibrated;

		public IkPlayer(Transform headTarget, Transform leftHandTarget, Transform rightHandTarget)
		{
			this.headTarget = headTarget;
			this.leftHandTarget = leftHandTarget;
			this.rightHandTarget = rightHandTarget;
		}

		public IkPlayer(TrackingTarget headTarget, TrackingTarget leftHandTarget, TrackingTarget rightHandTarget)
		{
			trackingTargets.Add(TrackingTargetType.Head, headTarget);
			this.headTarget = ((Component)headTarget).transform;
			trackingTargets.Add(TrackingTargetType.LeftHand, leftHandTarget);
			this.leftHandTarget = ((Component)leftHandTarget).transform;
			trackingTargets.Add(TrackingTargetType.RightHand, rightHandTarget);
			this.rightHandTarget = ((Component)rightHandTarget).transform;
		}

		private void init()
		{
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			Logger.LogDebug("Initializing ik player...");
			if ((Object)(object)avatar != (Object)null)
			{
				Logger.LogWarning("Avatar already exists, destroying it");
				Object.Destroy((Object)(object)avatar);
			}
			avatar = Object.Instantiate<GameObject>(GameObjectFinder.FindChildObjectByName("Ground Breaker", GameObjectFinder.FindObjectByName("ThirdPersonDisplay")));
			((Behaviour)avatar.GetComponent<Animator>()).enabled = false;
			((Behaviour)avatar.GetComponent<LeaningAnimator>()).enabled = false;
			((Behaviour)avatar.GetComponentInChildren<BonesStimulator>()).enabled = false;
			Logger.LogDebug($"Avatar instantiated {avatar.transform}, parent {((Component)this).transform}");
			avatar.transform.parent = ((Component)this).transform;
			avatar.transform.localPosition = Vector3.zero;
			avatar.transform.localRotation = Quaternion.identity;
			head = GameObjectFinder.FindChildObjectByName("head", avatar).transform;
			leftHand = GameObjectFinder.FindChildObjectByName("hand_l", avatar).transform;
			rightHand = GameObjectFinder.FindChildObjectByName("hand_r", avatar).transform;
			leftHandFingers = AddFingerTracking(leftHand, "l");
			rightHandFingers = AddFingerTracking(rightHand, "r");
			setReferences();
			avatarHeight = references.head.position.y - references.root.position.y;
			Logger.LogDebug($"Avatar height: {avatarHeight}");
			ik = avatar.AddComponent<VRIK>();
			ik.solver.spine.headTarget = headTarget;
			ik.solver.leftArm.target = leftHandTarget;
			ik.solver.rightArm.target = rightHandTarget;
			ik.references = references;
			ik.solver.plantFeet = false;
			Locomotion locomotion = ik.solver.locomotion;
			locomotion.maxVelocity *= 4f;
			Locomotion locomotion2 = ik.solver.locomotion;
			locomotion2.rootSpeed *= 4f;
			Locomotion locomotion3 = ik.solver.locomotion;
			locomotion3.stepThreshold /= 2f;
			Locomotion locomotion4 = ik.solver.locomotion;
			locomotion4.footDistance /= 1.25f;
			((Behaviour)ik).enabled = false;
			Logger.LogDebug($"Ik locomotion weight: {ik.solver.locomotion.weight}");
			Logger.LogDebug($"Ik locomotion max velocity: {ik.solver.locomotion.maxVelocity}");
			Logger.LogDebug($"Ik locomotion root speed: {ik.solver.locomotion.rootSpeed}");
			Logger.LogDebug($"Ik locomotion step speed: {ik.solver.locomotion.stepSpeed}");
			Logger.LogDebug($"Ik locomotion step threshold: {ik.solver.locomotion.stepThreshold}");
			Logger.LogDebug($"Ik left arm weight: {ik.solver.leftArm.positionWeight}");
			Logger.LogDebug($"Ik right arm weight: {ik.solver.rightArm.positionWeight}");
			((Component)this).gameObject.AddComponent<Gizmo>();
			((Component)headTarget).gameObject.AddComponent<Gizmo>();
			((Component)leftHandTarget).gameObject.AddComponent<Gizmo>();
			((Component)rightHandTarget).gameObject.AddComponent<Gizmo>();
		}

		private void setReferences()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Expected O, but got Unknown
			references = new References();
			references.pelvis = GameObjectFinder.FindChildObjectByName("pelvis", avatar).transform;
			references.root = references.pelvis.parent.parent;
			references.spine = GameObjectFinder.FindChildObjectByName("spine_01", references.pelvis).transform;
			references.chest = GameObjectFinder.FindChildObjectByName("spine_02", references.spine).transform;
			references.neck = GameObjectFinder.FindChildObjectByName("neck_01", references.chest).transform;
			references.head = head;
			references.leftShoulder = GameObjectFinder.FindChildObjectByName("clavicle_l", references.chest).transform;
			references.leftUpperArm = GameObjectFinder.FindChildObjectByName("upperarm_l", references.leftShoulder).transform;
			references.leftForearm = GameObjectFinder.FindChildObjectByName("lowerarm_l", references.leftUpperArm).transform;
			references.leftHand = leftHand;
			references.rightShoulder = GameObjectFinder.FindChildObjectByName("clavicle_r", references.chest).transform;
			references.rightUpperArm = GameObjectFinder.FindChildObjectByName("upperarm_r", references.rightShoulder).transform;
			references.rightForearm = GameObjectFinder.FindChildObjectByName("lowerarm_r", references.rightUpperArm).transform;
			references.rightHand = rightHand;
			references.leftThigh = GameObjectFinder.FindChildObjectByName("thigh_l", references.pelvis).transform;
			references.leftCalf = GameObjectFinder.FindChildObjectByName("calf_l", references.leftThigh).transform;
			references.leftFoot = GameObjectFinder.FindChildObjectByName("foot_l", references.leftCalf).transform;
			references.rightThigh = GameObjectFinder.FindChildObjectByName("thigh_r", references.pelvis).transform;
			references.rightCalf = GameObjectFinder.FindChildObjectByName("calf_r", references.rightThigh).transform;
			references.rightFoot = GameObjectFinder.FindChildObjectByName("foot_r", references.rightCalf).transform;
		}

		private void OnDestroy()
		{
			Logger.LogInfo("Destroying ik player...");
		}

		private void OnEnable()
		{
			Logger.LogInfo("Enabling ik player...");
		}

		private void OnDisable()
		{
			Logger.LogInfo("Disabling ik player...");
		}

		private void Update()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (calibrating == true)
			{
				setScale(getScale(headTargetParent.position));
			}
		}

		private float getScale(Vector3 headPosition)
		{
			//IL_0000: 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)
			return (headPosition.y - ik.references.root.position.y) / avatarHeight + 0.1f;
		}

		public void setScale(float scale)
		{
			//IL_001e: 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_0038: 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_0064: 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)
			this.scale = scale;
			this.OnScaleChanged?.Invoke(scale);
			Vector3 val = Vector3.one * 1.15f;
			Logger.LogDebug($"Setting object scale to {val * scale} ({scale})");
			ik.references.root.localScale = val * scale;
		}

		public void calibrate(Transform headTargetParent, Transform leftHandTargetParent, Transform rightHandTargetParent)
		{
			calibrate();
			this.headTargetParent = headTargetParent;
			trackingTargets[TrackingTargetType.Head].StartCalibration(head, headTargetParent);
			trackingTargets[TrackingTargetType.LeftHand].StartCalibration(leftHand, leftHandTargetParent);
			trackingTargets[TrackingTargetType.RightHand].StartCalibration(rightHand, rightHandTargetParent);
			calibrating = true;
		}

		internal void calibrate()
		{
			init();
			this.OnCalibrating?.Invoke();
		}

		public void calibrated(float? scale)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			Enumeration.ForEach<TrackingTarget>((IEnumerable<TrackingTarget>)trackingTargets.Values, (Action<TrackingTarget>)delegate(TrackingTarget t)
			{
				t.FinishCalibration();
			});
			if ((Object)(object)headTargetParent != (Object)null)
			{
				setScale(getScale(headTargetParent.position));
			}
			else
			{
				setScale(scale.GetValueOrDefault(1f));
			}
			calibrating = false;
			((Behaviour)ik).enabled = true;
			this.OnCalibrated?.Invoke();
		}

		private Transform TrackingTargetOrDefault(TrackingTargetType type, Transform defaultTransform)
		{
			TrackingTarget valueOrDefault = trackingTargets.GetValueOrDefault(type, null);
			return ((valueOrDefault != null) ? ((Component)valueOrDefault).transform : null) ?? defaultTransform;
		}

		private static CustomHandUpdater AddFingerTracking(Transform handRoot, string boneName)
		{
			//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_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_023c: 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_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObjectFinder.FindChildObjectByName("thumb_01_" + boneName, handRoot);
			Transform child = val.transform.GetChild(0);
			Transform child2 = ((Component)child).transform.GetChild(0);
			GameObject val2 = GameObjectFinder.FindChildObjectByName("index_01_" + boneName, handRoot);
			Transform child3 = val2.transform.GetChild(0);
			Transform child4 = ((Component)child3).transform.GetChild(0);
			((Component)child3).gameObject.AddComponent<Gizmo>();
			GameObject val3 = GameObjectFinder.FindChildObjectByName("middle_01_" + boneName, handRoot);
			Transform child5 = val3.transform.GetChild(0);
			Transform child6 = ((Component)child5).transform.GetChild(0);
			GameObject val4 = GameObjectFinder.FindChildObjectByName("ring_01_" + boneName, handRoot);
			Transform child7 = val4.transform.GetChild(0);
			Transform child8 = ((Component)child7).transform.GetChild(0);
			GameObject val5 = GameObjectFinder.FindChildObjectByName("pinky_01_" + boneName, handRoot);
			Transform child9 = val5.transform.GetChild(0);
			Transform child10 = ((Component)child9).transform.GetChild(0);
			CustomHandUpdater customHandUpdater = new CustomHandUpdater();
			Finger finger = new Finger(null, 110f);
			finger.WithBone(val.transform).WithBone(child).WithBone(child2, 0.75f);
			customHandUpdater.fingers.Add(FingerType.Thumb, finger);
			Finger finger2 = new Finger(Vector3.back + Vector3.down * 0.1f);
			finger2.WithBone(val2.transform).WithBone(child3, 1.25f).WithBone(child4);
			customHandUpdater.fingers.Add(FingerType.Index, finger2);
			Finger finger3 = new Finger();
			finger3.WithBone(val3.transform).WithBone(child5, 1.25f).WithBone(child6);
			customHandUpdater.fingers.Add(FingerType.Middle, finger3);
			Finger finger4 = new Finger(Vector3.back + Vector3.up * 0.2f);
			finger4.WithBone(val4.transform).WithBone(child7, 1.25f).WithBone(child8);
			customHandUpdater.fingers.Add(FingerType.Ring, finger4);
			Finger finger5 = new Finger(Vector3.back + Vector3.up * 0.3f);
			finger5.WithBone(val5.transform).WithBone(child9, 1.25f).WithBone(child10);
			customHandUpdater.fingers.Add(FingerType.Pinky, finger5);
			return customHandUpdater;
		}

		internal void UpdateFingerCurl(HandType hand, FingerType finger, float curl)
		{
			switch (hand)
			{
			case HandType.Left:
				leftHandFingers?.OnBoneTransformsUpdated(finger, curl);
				break;
			case HandType.Right:
				rightHandFingers?.OnBoneTransformsUpdated(finger, curl);
				break;
			}
		}
	}
	public class TrackingTarget : MonoBehaviour
	{
		private static PluginLogger Logger = PluginLogger.GetLogger<TrackingTarget>();

		public NetworkTransform target;

		private Transform trackingTarget;

		public Vector3 positionOffset;

		public Quaternion rotationOffset;

		public bool calibrating;

		public TrackingTarget(NetworkTransform target)
		{
			if ((Object)(object)target == (Object)null)
			{
				throw new ArgumentException("Target does not have a NetworkTransform component.");
			}
			this.target = target;
		}

		public TrackingTarget(GameObject target)
			: this(target.GetComponent<NetworkTransform>())
		{
		}

		public void StartCalibration(Transform trackingTarget, Transform anchor)
		{
			//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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			calibrating = true;
			this.trackingTarget = trackingTarget;
			((Component)this).transform.SetParent(anchor, false);
			positionOffset = Vector3.zero;
			rotationOffset = Quaternion.identity;
		}

		public void FinishCalibration()
		{
			calibrating = false;
		}

		private void Start()
		{
			((Component)this).gameObject.AddComponent<Gizmo>();
			((Component)target).gameObject.AddComponent<Gizmo>();
			DebugLine obj = ((Component)this).gameObject.AddComponent<DebugLine>();
			obj.start = ((Component)target).transform;
			obj.end = ((Component)this).transform;
		}

		private void Update()
		{
			if (calibrating)
			{
				UpdateCalibrationTransform();
			}
			else
			{
				UpdateTransform();
			}
		}

		private void UpdateTransform()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target != (Object)null)
			{
				((Component)target).transform.rotation = ((Component)this).transform.rotation * rotationOffset;
				((Component)target).transform.position = ((Component)this).transform.position + ((Component)this).transform.rotation * positionOffset;
			}
		}

		private void UpdateCalibrationTransform()
		{
			//IL_001f: 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)
			if ((Object)(object)trackingTarget != (Object)null)
			{
				((Component)target).transform.position = trackingTarget.position;
				((Component)target).transform.rotation = trackingTarget.rotation;
			}
		}
	}
}
namespace TTIK.Ik.FingerTracking
{
	internal class CustomHandUpdater
	{
		public static FingerType[] ALL_FINGER_TYPES = new FingerType[5]
		{
			FingerType.Thumb,
			FingerType.Index,
			FingerType.Middle,
			FingerType.Ring,
			FingerType.Pinky
		};

		public Dictionary<FingerType, Finger> fingers = new Dictionary<FingerType, Finger>();

		public void OnBoneTransformsUpdated(FingerType fingerType, float value)
		{
			if (fingers.TryGetValue(fingerType, out var value2))
			{
				value2.CurlFinger(value);
			}
		}
	}
	internal enum Bone
	{
		Root,
		Wrist,
		Thumb0,
		Thumb1,
		Thumb2,
		Thumb3,
		IndexFinger0,
		IndexFinger1,
		IndexFinger2,
		IndexFinger3,
		IndexFinger4,
		MiddleFinger0,
		MiddleFinger1,
		MiddleFinger2,
		MiddleFinger3,
		MiddleFinger4,
		RingFinger0,
		RingFinger1,
		RingFinger2,
		RingFinger3,
		RingFinger4,
		PinkyFinger0,
		PinkyFinger1,
		PinkyFinger2,
		PinkyFinger3,
		PinkyFinger4,
		Aux_Thumb,
		Aux_IndexFinger,
		Aux_MiddleFinger,
		Aux_RingFinger,
		Aux_PinkyFinger,
		Count
	}
	public class Finger
	{
		private Vector3 axis = Vector3.back;

		private float totalCurl = 180f;

		private Dictionary<Transform, float> bones = new Dictionary<Transform, float>();

		private Dictionary<Transform, Quaternion> originalRotations = new Dictionary<Transform, Quaternion>();

		public Finger(Vector3? axis = null, float totalCurl = 180f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			this.axis = (Vector3)(((??)axis) ?? this.axis);
			this.totalCurl = totalCurl;
		}

		public Finger(Dictionary<Transform, float> bones, Vector3? axis = null, float totalCurl = 180f)
			: this(axis, totalCurl)
		{
			this.bones = bones;
		}

		public Finger WithBone(Transform transform)
		{
			AddBone(transform);
			return this;
		}

		public Finger WithBone(Transform transform, float factor)
		{
			AddBone(transform, factor);
			return this;
		}

		public void AddBone(Transform transform)
		{
			AddBone(transform, 1f);
		}

		public void AddBone(Transform transform, float factor)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			bones.Add(transform, factor);
			originalRotations.Add(transform, transform.localRotation);
		}

		public void CurlFinger(float factor)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0058: 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)
			float num = factor / bones.Values.Sum();
			foreach (KeyValuePair<Transform, float> bone in bones)
			{
				bone.Deconstruct(out var key, out var value);
				Transform val = key;
				float num2 = value;
				Quaternion val2 = originalRotations[val];
				float num3 = num2 * num;
				val.localRotation = val2 * Quaternion.AngleAxis(totalCurl * num3, axis);
			}
		}
	}
	public enum FingerType
	{
		Thumb,
		Index,
		Middle,
		Ring,
		Pinky
	}
	public enum HandType
	{
		Left,
		Right
	}
}