Decompiled source of Y4NGZInteractions v1.0.3

Y4NGZInteractions.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Y4NGZInteractions.InteractionAnimationApi;
using Y4NGZInteractions.InteractionAnimationApi.Authoring;
using Y4NGZInteractions.InteractionAnimationApi.Presenters;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: InternalsVisibleTo("Y4NGZInteractions.Tests")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Y4NGZInteractions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Consumer-agnostic local animation presentation API for Lethal Company")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("Y4NGZInteractions")]
[assembly: AssemblyTitle("Y4NGZInteractions")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Y4NGZInteractions
{
	internal sealed class InteractionRuntimeHost : MonoBehaviour
	{
		private Harmony harmony;

		private ManualLogSource log;

		private bool applicationQuitting;

		private bool tornDown;

		internal void Initialize(Harmony harmony, ManualLogSource log)
		{
			this.harmony = harmony;
			this.log = log;
			Application.quitting += OnApplicationQuitting;
			try
			{
				((Component)this).gameObject.AddComponent<MetarigRootWriteBackOwnerRunner>();
			}
			catch (Exception ex)
			{
				if (log != null)
				{
					log.LogWarning((object)("[RestoreSeam.metarigroot] early_runner_failed: " + ex.Message + " (the late host pass still runs)."));
				}
			}
		}

		private void LateUpdate()
		{
			InteractionAnimationApiRestoreDiagnostics.BeginCoordinatorLateUpdateTick();
			try
			{
				InteractionAnimationApiPlugin.Tick(Time.deltaTime);
			}
			finally
			{
				InteractionAnimationApiRestoreDiagnostics.EndCoordinatorLateUpdateTick();
			}
			ArmsMetarigWriteBackOwner.LateUpdateTick();
			MetarigRootWriteBackOwner.LateUpdateTick("late");
			MovementStartProbe.LateUpdateTick();
		}

		private void OnApplicationQuit()
		{
			applicationQuitting = true;
		}

		private void OnApplicationQuitting()
		{
			applicationQuitting = true;
			TearDown();
		}

		private void OnDestroy()
		{
			Application.quitting -= OnApplicationQuitting;
			if (!applicationQuitting)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogError((object)("Y4NGZInteractions runtime host destroyed outside application shutdown " + string.Format("(frame={0}, host='{1}'). ", Time.frameCount, ((Object)(object)((Component)this).gameObject != (Object)null) ? ((Object)((Component)this).gameObject).name : "<null>") + "The interaction animation API and all Harmony patches are going down with it."));
				}
			}
			TearDown();
		}

		private void TearDown()
		{
			if (tornDown)
			{
				return;
			}
			tornDown = true;
			try
			{
				InteractionAnimationApiPlugin.Shutdown();
				InteractionAnimationApiRestoreDiagnostics.Shutdown();
			}
			catch (Exception ex)
			{
				ManualLogSource obj = log;
				if (obj != null)
				{
					obj.LogWarning((object)("Y4NGZInteractions shutdown warning: " + ex.Message));
				}
			}
			Harmony obj2 = harmony;
			if (obj2 != null)
			{
				obj2.UnpatchSelf();
			}
		}
	}
	internal static class MovementStartProbe
	{
		private const int PreFrames = 6;

		private const int PostFrames = 45;

		private const float InputRiseThreshold = 0.1f;

		private const float HitchSeconds = 0.05f;

		private const float HitchLogIntervalSeconds = 0.2f;

		private const string Tag = "[MovementStartProbe] ";

		private static readonly FieldInfo WalkForceField = AccessTools.Field(typeof(PlayerControllerB), "walkForce");

		private static readonly FieldInfo SprintMultiplierField = AccessTools.Field(typeof(PlayerControllerB), "sprintMultiplier");

		private static readonly FieldInfo IsWalkingField = AccessTools.Field(typeof(PlayerControllerB), "isWalking");

		private static readonly FieldInfo IsJumpingField = AccessTools.Field(typeof(PlayerControllerB), "isJumping");

		private static readonly FieldInfo IsFallingNoJumpField = AccessTools.Field(typeof(PlayerControllerB), "isFallingNoJump");

		private static readonly FieldInfo IsFallingFromJumpField = AccessTools.Field(typeof(PlayerControllerB), "isFallingFromJump");

		private static readonly FieldInfo CrouchMeterField = AccessTools.Field(typeof(PlayerControllerB), "crouchMeter");

		private static readonly string[] Ring = new string[6];

		private static int ringCount;

		private static int ringNext;

		private static int postRemaining;

		private static int startCount;

		private static bool wasWalking;

		private static float lastInputMagnitude;

		private static Vector3 lastPosition;

		private static bool hasLastPosition;

		private static float lastDeltaTime;

		private static float nextHitchLogAllowedAt;

		private static bool failureLogged;

		private static PlayerControllerB lastPlayer;

		private static Vector3 lastCameraWorld;

		private static bool hasLastCameraWorld;

		internal static void LateUpdateTick()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: 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_00d4: 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_00dd: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0314: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_047e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0365: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Unknown result type (might be due to invalid IL or missing references)
			//IL_07fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0800: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!InteractionAnimationApiRestoreDiagnostics.MovementStartProbeEnabled)
				{
					return;
				}
				PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null);
				if ((Object)(object)val == (Object)null && (Object)(object)StartOfRound.Instance != (Object)null)
				{
					val = StartOfRound.Instance.localPlayerController;
				}
				if ((Object)(object)val == (Object)null || val.isPlayerDead || (Object)(object)((Component)val).transform == (Object)null)
				{
					hasLastPosition = false;
					return;
				}
				if (val != lastPlayer)
				{
					lastPlayer = val;
					hasLastPosition = false;
					ringCount = 0;
					ringNext = 0;
					postRemaining = 0;
				}
				float deltaTime = Time.deltaTime;
				Vector2 moveInputVector = val.moveInputVector;
				float magnitude = ((Vector2)(ref moveInputVector)).magnitude;
				Vector3 position = ((Component)val).transform.position;
				Vector3 val2 = (hasLastPosition ? (position - lastPosition) : Vector3.zero);
				Vector2 val3 = new Vector2(val2.x, val2.z);
				float magnitude2 = ((Vector2)(ref val3)).magnitude;
				CharacterController thisController = val.thisController;
				Vector3 val4 = (((Object)(object)thisController != (Object)null) ? thisController.velocity : Vector3.zero);
				val3 = new Vector2(val4.x, val4.z);
				float magnitude3 = ((Vector2)(ref val3)).magnitude;
				string arg = (((Object)(object)thisController != (Object)null) ? thisController.isGrounded.ToString() : "n/a");
				bool flag = ReadBool(IsWalkingField, val);
				Vector3 val5 = ReadVector3(WalkForceField, val);
				float num = ReadFloat(SprintMultiplierField, val);
				float num2 = ReadFloat(CrouchMeterField, val);
				string text = "n/a";
				if ((Object)(object)val.gameplayCamera != (Object)null)
				{
					Vector3 val6 = ((Component)val).transform.InverseTransformPoint(((Component)val.gameplayCamera).transform.position);
					text = $"({val6.x:0.000},{val6.y:0.000},{val6.z:0.000})";
				}
				string text2 = "n/a";
				string text3 = "n/a";
				string text4 = "n/a";
				if ((Object)(object)val.playerBodyAnimator != (Object)null && (Object)(object)((Component)val.playerBodyAnimator).transform != (Object)null)
				{
					Vector3 localPosition = ((Component)val.playerBodyAnimator).transform.localPosition;
					text2 = $"({localPosition.x:0.000},{localPosition.y:0.000},{localPosition.z:0.000})";
				}
				if ((Object)(object)val.playerModelArmsMetarig != (Object)null)
				{
					Vector3 localPosition2 = val.playerModelArmsMetarig.localPosition;
					text3 = $"({localPosition2.x:0.000},{localPosition2.y:0.000},{localPosition2.z:0.000})";
				}
				if ((Object)(object)val.gameplayCamera != (Object)null)
				{
					Vector3 position2 = ((Component)val.gameplayCamera).transform.position;
					if (hasLastCameraWorld)
					{
						Vector3 val7 = position2 - lastCameraWorld;
						val3 = new Vector2(val7.x, val7.z);
						text4 = $"{((Vector2)(ref val3)).magnitude:0.0000}";
					}
					lastCameraWorld = position2;
					hasLastCameraWorld = true;
				}
				else
				{
					hasLastCameraWorld = false;
				}
				string arg2 = "n/a";
				Animator playerBodyAnimator = val.playerBodyAnimator;
				if ((Object)(object)playerBodyAnimator != (Object)null && ((Behaviour)playerBodyAnimator).isActiveAndEnabled && (Object)(object)playerBodyAnimator.runtimeAnimatorController != (Object)null && playerBodyAnimator.layerCount > 0)
				{
					AnimatorStateInfo currentAnimatorStateInfo = playerBodyAnimator.GetCurrentAnimatorStateInfo(0);
					bool flag2 = playerBodyAnimator.IsInTransition(0);
					arg2 = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).shortNameHash + (flag2 ? "*" : string.Empty);
				}
				string text5 = $"frame={Time.frameCount} dt={deltaTime * 1000f:0.0}ms " + $"udt={Time.unscaledDeltaTime * 1000f:0.0}ms " + $"input=({moveInputVector.x:0.00},{moveInputVector.y:0.00}) walking={flag} " + $"sprinting={val.isSprinting} walkForce={((Vector3)(ref val5)).magnitude:0.000} " + $"sprintMult={num:0.00} speed={val.movementSpeed:0.00} " + $"carry={val.carryWeight:0.000} vel={magnitude3:0.000} " + $"dPos={magnitude2:0.0000} dPosY={val2.y:0.0000} grounded={arg} " + $"fallNoJump={ReadBool(IsFallingNoJumpField, val)} " + $"fallFromJump={ReadBool(IsFallingFromJumpField, val)} " + $"jumping={ReadBool(IsJumpingField, val)} crouching={val.isCrouching} " + $"crouchMeter={num2:0.00} hindered={val.isMovementHindered} " + $"disableMove={val.disableMoveInput} special={val.inSpecialInteractAnimation} " + "camLocal=" + text + " camWorldD=" + text4 + " root=" + text2 + " arms=" + text3 + " " + $"state={arg2} timeScale={Time.timeScale:0.00}";
				bool flag3 = hasLastPosition && magnitude >= 0.1f && lastInputMagnitude < 0.1f;
				bool flag4 = hasLastPosition && flag && !wasWalking;
				if (hasLastPosition && deltaTime > 0.05f && Time.realtimeSinceStartup >= nextHitchLogAllowedAt)
				{
					nextHitchLogAllowedAt = Time.realtimeSinceStartup + 0.2f;
					ManualLogSource staticLogger = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
					if (staticLogger != null)
					{
						staticLogger.LogInfo((object)("[MovementStartProbe] " + $"hitch: prevDt={lastDeltaTime * 1000f:0.0}ms " + text5));
					}
				}
				if ((flag3 || flag4) && postRemaining <= 0)
				{
					startCount++;
					string arg3 = ((flag3 && flag4) ? "input+walking" : (flag3 ? "input" : "walking"));
					ManualLogSource staticLogger2 = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
					if (staticLogger2 != null)
					{
						staticLogger2.LogInfo((object)("[MovementStartProbe] " + $"movement_start #{startCount} trigger='{arg3}' " + $"frame={Time.frameCount} preFrames={ringCount} postFrames={45}."));
					}
					for (int i = 0; i < ringCount; i++)
					{
						int num3 = (ringNext - ringCount + i + 6) % 6;
						ManualLogSource staticLogger3 = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
						if (staticLogger3 != null)
						{
							staticLogger3.LogInfo((object)("[MovementStartProbe] " + $"pre#{startCount}: " + Ring[num3]));
						}
					}
					ringCount = 0;
					postRemaining = 45;
				}
				if (postRemaining > 0)
				{
					ManualLogSource staticLogger4 = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
					if (staticLogger4 != null)
					{
						staticLogger4.LogInfo((object)("[MovementStartProbe] " + $"post#{startCount}: " + text5));
					}
					postRemaining--;
					if (postRemaining == 0)
					{
						ManualLogSource staticLogger5 = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
						if (staticLogger5 != null)
						{
							staticLogger5.LogInfo((object)("[MovementStartProbe] " + $"movement_start_end #{startCount} frame={Time.frameCount}."));
						}
					}
				}
				else
				{
					Ring[ringNext] = text5;
					ringNext = (ringNext + 1) % 6;
					if (ringCount < 6)
					{
						ringCount++;
					}
				}
				wasWalking = flag;
				lastInputMagnitude = magnitude;
				lastPosition = position;
				hasLastPosition = true;
				lastDeltaTime = deltaTime;
			}
			catch (Exception ex)
			{
				if (!failureLogged)
				{
					failureLogged = true;
					ManualLogSource staticLogger6 = InteractionAnimationApiRestoreDiagnostics.StaticLogger;
					if (staticLogger6 != null)
					{
						staticLogger6.LogWarning((object)("[MovementStartProbe] tick failed; probe disabled for this session: " + ex.Message));
					}
				}
			}
		}

		private static bool ReadBool(FieldInfo field, PlayerControllerB player)
		{
			try
			{
				bool flag = default(bool);
				int num;
				if (field != null)
				{
					object value = field.GetValue(player);
					if (value is bool)
					{
						flag = (bool)value;
						num = 1;
					}
					else
					{
						num = 0;
					}
				}
				else
				{
					num = 0;
				}
				return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static float ReadFloat(FieldInfo field, PlayerControllerB player)
		{
			try
			{
				return (field != null && field.GetValue(player) is float num) ? num : float.NaN;
			}
			catch
			{
				return float.NaN;
			}
		}

		private static Vector3 ReadVector3(FieldInfo field, PlayerControllerB player)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_002a: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return (field != null && field.GetValue(player) is Vector3 val) ? val : Vector3.zero;
			}
			catch
			{
				return Vector3.zero;
			}
		}
	}
	[BepInPlugin("com.y4ngz.interactions", "Y4NGZInteractions", "1.0.3")]
	internal sealed class Plugin : BaseUnityPlugin
	{
		internal const string Guid = "com.y4ngz.interactions";

		internal const string Name = "Y4NGZInteractions";

		internal const string Version = "1.0.3";

		internal const string HostObjectName = "Y4NGZInteractions_Host";

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Log { get; private set; }

		internal static InteractionRuntimeHost Host { get; private set; }

		private void Awake()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0033: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony harmony = new Harmony("com.y4ngz.interactions");
			GameObject val = new GameObject("Y4NGZInteractions_Host")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			Host = val.AddComponent<InteractionRuntimeHost>();
			Host.Initialize(harmony, ((BaseUnityPlugin)this).Logger);
			InitializeModule("Interaction Animation API", delegate
			{
				InteractionAnimationApiPlugin.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			});
			InitializeModule("Interaction Animation API Restoration", delegate
			{
				InteractionAnimationApiRestoreDiagnostics.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
			});
			InitializeModule("Interaction Animation API Spawn Hooks", delegate
			{
				harmony.PatchAll();
			});
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Y4NGZInteractions v1.0.3 loaded.");
		}

		private void InitializeModule(string label, Action initialize)
		{
			try
			{
				initialize();
				((BaseUnityPlugin)this).Logger.LogInfo((object)(label + " initialized."));
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"{label} initialization failed: {arg}");
			}
		}
	}
	internal static class BuildVersion
	{
		internal const string Value = "1.0.3";
	}
}
namespace Y4NGZInteractions.InteractionAnimationApi
{
	internal static class InteractionAnimationApiPlugin
	{
		private static ManualLogSource logger;

		private static InteractionAnimationCoordinator coordinator;

		private static bool initialized;

		internal static void Initialize(ConfigFile config, ManualLogSource log)
		{
			if (!initialized)
			{
				logger = log;
				coordinator = new InteractionAnimationCoordinator(logger);
				LCInteractionAnimationAPI.Initialize(coordinator);
				initialized = true;
				Assembly assembly = typeof(InteractionAnimationApiPlugin).Assembly;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)("[LCInteractionAnimationAPI] api.initialized: standalone local presentation API ready " + $"(version={assembly.GetName().Version}, location='{assembly.Location}')."));
				}
				WarnOnShadowCopies(assembly);
			}
		}

		private static void WarnOnShadowCopies(Assembly assembly)
		{
			try
			{
				string location = assembly.Location;
				string pluginPath = Paths.PluginPath;
				if (string.IsNullOrEmpty(location) || string.IsNullOrEmpty(pluginPath) || !Directory.Exists(pluginPath))
				{
					return;
				}
				string[] files = Directory.GetFiles(pluginPath, Path.GetFileName(location), SearchOption.AllDirectories);
				string[] array = DuplicateInstallPolicy.FindShadowCopies(location, files);
				foreach (string text in array)
				{
					ManualLogSource obj = logger;
					if (obj != null)
					{
						obj.LogError((object)("[LCInteractionAnimationAPI] duplicate_install_detected: a second '" + Path.GetFileName(location) + "' exists at '" + text + "'. Consumers can bind to that never-initialized copy and report interaction_animation_api_not_initialized for the whole session even though this copy initialized. Remove or update the stale install."));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogWarning((object)("[LCInteractionAnimationAPI] duplicate_install_scan_failed: " + ex.Message));
				}
			}
		}

		internal static void Tick(float deltaTime)
		{
			if (initialized)
			{
				coordinator?.Tick(deltaTime);
			}
		}

		internal static void Shutdown()
		{
			if (initialized)
			{
				coordinator?.Shutdown();
				LiveBodyAnimatorPresenter.ShutdownBundleCache();
				LCInteractionAnimationAPI.Shutdown();
				coordinator = null;
				initialized = false;
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogInfo((object)"[LCInteractionAnimationAPI] api.shutdown: restoration complete.");
				}
				logger = null;
			}
		}
	}
	internal enum AnimatorStateRestoreMode
	{
		Fresh,
		Crossfade,
		Replay
	}
	internal sealed class AnimatorStateSnapshot
	{
		private readonly struct LayerSnapshot
		{
			public readonly int FullPathHash;

			public readonly float NormalizedTime;

			public readonly float Weight;

			public readonly bool InTransition;

			public LayerSnapshot(int fullPathHash, float normalizedTime, float weight, bool inTransition)
			{
				FullPathHash = fullPathHash;
				NormalizedTime = normalizedTime;
				Weight = weight;
				InTransition = inTransition;
			}
		}

		private readonly struct ParameterSnapshot
		{
			private readonly int nameHash;

			private readonly AnimatorControllerParameterType type;

			private readonly bool boolValue;

			private readonly int intValue;

			private readonly float floatValue;

			private ParameterSnapshot(int nameHash, AnimatorControllerParameterType type, bool boolValue, int intValue, float floatValue)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				this.nameHash = nameHash;
				this.type = type;
				this.boolValue = boolValue;
				this.intValue = intValue;
				this.floatValue = floatValue;
			}

			public static ParameterSnapshot Capture(Animator animator, AnimatorControllerParameter parameter)
			{
				//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_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected I4, but got Unknown
				//IL_0070: 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_004c: 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)
				AnimatorControllerParameterType val = parameter.type;
				return (val - 1) switch
				{
					3 => new ParameterSnapshot(parameter.nameHash, parameter.type, animator.GetBool(parameter.nameHash), 0, 0f), 
					2 => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, animator.GetInteger(parameter.nameHash), 0f), 
					0 => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, 0, animator.GetFloat(parameter.nameHash)), 
					_ => new ParameterSnapshot(parameter.nameHash, parameter.type, boolValue: false, 0, 0f), 
				};
			}

			public void Restore(Animator animator)
			{
				//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_0007: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Expected I4, but got Unknown
				AnimatorControllerParameterType val = type;
				switch (val - 1)
				{
				case 3:
					animator.SetBool(nameHash, boolValue);
					break;
				case 2:
					animator.SetInteger(nameHash, intValue);
					break;
				case 0:
					animator.SetFloat(nameHash, floatValue);
					break;
				case 1:
					break;
				}
			}
		}

		private const float CrossfadeDurationSeconds = 0.12f;

		private readonly LayerSnapshot[] layers;

		private readonly ParameterSnapshot[] parameters;

		public RuntimeAnimatorController RuntimeAnimatorController { get; }

		public float Speed { get; }

		public bool? CapturedCrouching { get; set; }

		private AnimatorStateSnapshot(RuntimeAnimatorController runtimeAnimatorController, float speed, LayerSnapshot[] layers, ParameterSnapshot[] parameters)
		{
			RuntimeAnimatorController = runtimeAnimatorController;
			Speed = speed;
			this.layers = layers ?? Array.Empty<LayerSnapshot>();
			this.parameters = parameters ?? Array.Empty<ParameterSnapshot>();
		}

		public static AnimatorStateSnapshot Capture(Animator animator)
		{
			//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)
			if ((Object)(object)animator == (Object)null)
			{
				return null;
			}
			try
			{
				RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
				float speed = animator.speed;
				if (!animator.isInitialized)
				{
					return new AnimatorStateSnapshot(runtimeAnimatorController, speed, Array.Empty<LayerSnapshot>(), Array.Empty<ParameterSnapshot>());
				}
				int num = Math.Max(0, animator.layerCount);
				LayerSnapshot[] array = new LayerSnapshot[num];
				for (int i = 0; i < num; i++)
				{
					AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(i);
					array[i] = new LayerSnapshot(((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime, animator.GetLayerWeight(i), animator.IsInTransition(i));
				}
				AnimatorControllerParameter[] array2 = animator.parameters ?? Array.Empty<AnimatorControllerParameter>();
				ParameterSnapshot[] array3 = new ParameterSnapshot[array2.Length];
				for (int j = 0; j < array2.Length; j++)
				{
					AnimatorControllerParameter parameter = array2[j];
					array3[j] = ParameterSnapshot.Capture(animator, parameter);
				}
				return new AnimatorStateSnapshot(runtimeAnimatorController, speed, array, array3);
			}
			catch
			{
				return null;
			}
		}

		public int ReapplyParameters(Animator animator)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < parameters.Length; i++)
			{
				try
				{
					parameters[i].Restore(animator);
					num++;
				}
				catch
				{
				}
			}
			return num;
		}

		public bool TryReapplyLayerState(Animator animator, int layerIndex)
		{
			if ((Object)(object)animator == (Object)null || layerIndex < 0 || layerIndex >= layers.Length || layerIndex >= animator.layerCount)
			{
				return false;
			}
			try
			{
				LayerSnapshot layerSnapshot = layers[layerIndex];
				if (layerSnapshot.InTransition || layerSnapshot.FullPathHash == 0 || !animator.HasState(layerIndex, layerSnapshot.FullPathHash))
				{
					return false;
				}
				animator.SetLayerWeight(layerIndex, layerSnapshot.Weight);
				animator.Play(layerSnapshot.FullPathHash, layerIndex, layerSnapshot.NormalizedTime);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public bool Restore(Animator animator)
		{
			return Restore(animator, RuntimeAnimatorController);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator: true);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator, AnimatorStateRestoreMode.Replay);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator, AnimatorStateRestoreMode restoreMode)
		{
			return Restore(animator, expectedCurrentController, rebindAnimator, restoreMode, null, restoreBaseLayerState: true);
		}

		public bool Restore(Animator animator, RuntimeAnimatorController expectedCurrentController, bool rebindAnimator, AnimatorStateRestoreMode restoreMode, Action syncParametersBeforeStateReplay, bool restoreBaseLayerState, Action afterControllerAssigned = null)
		{
			if ((Object)(object)animator == (Object)null)
			{
				return false;
			}
			try
			{
				if ((Object)(object)expectedCurrentController != (Object)null && (Object)(object)animator.runtimeAnimatorController != (Object)(object)expectedCurrentController)
				{
					return false;
				}
				animator.runtimeAnimatorController = RuntimeAnimatorController;
				if (rebindAnimator)
				{
					animator.Rebind();
				}
				if (afterControllerAssigned != null)
				{
					try
					{
						afterControllerAssigned();
					}
					catch
					{
					}
				}
				animator.speed = Speed;
				for (int i = 0; i < parameters.Length; i++)
				{
					parameters[i].Restore(animator);
				}
				if (syncParametersBeforeStateReplay != null)
				{
					try
					{
						syncParametersBeforeStateReplay();
					}
					catch
					{
					}
				}
				int num = Math.Min(animator.layerCount, layers.Length);
				for (int j = 0; j < num; j++)
				{
					LayerSnapshot layerSnapshot = layers[j];
					animator.SetLayerWeight(j, layerSnapshot.Weight);
					if ((j != 0 || restoreBaseLayerState) && layerSnapshot.FullPathHash != 0)
					{
						switch (restoreMode)
						{
						case AnimatorStateRestoreMode.Crossfade:
							animator.CrossFadeInFixedTime(layerSnapshot.FullPathHash, 0.12f, j, Mathf.Repeat(layerSnapshot.NormalizedTime, 1f));
							break;
						case AnimatorStateRestoreMode.Replay:
							animator.Play(layerSnapshot.FullPathHash, j, layerSnapshot.NormalizedTime);
							break;
						}
					}
				}
				animator.Update(0f);
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
	internal static class DuplicateInstallPolicy
	{
		internal static string[] FindShadowCopies(string loadedAssemblyPath, IEnumerable<string> candidatePaths)
		{
			if (string.IsNullOrWhiteSpace(loadedAssemblyPath) || candidatePaths == null)
			{
				return Array.Empty<string>();
			}
			string text = TryNormalize(loadedAssemblyPath);
			if (text == null)
			{
				return Array.Empty<string>();
			}
			SortedSet<string> sortedSet = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (string candidatePath in candidatePaths)
			{
				if (!string.IsNullOrWhiteSpace(candidatePath))
				{
					string text2 = TryNormalize(candidatePath);
					if (text2 != null && !string.Equals(text2, text, StringComparison.OrdinalIgnoreCase))
					{
						sortedSet.Add(text2);
					}
				}
			}
			string[] array = new string[sortedSet.Count];
			sortedSet.CopyTo(array);
			return array;
		}

		private static string TryNormalize(string path)
		{
			try
			{
				return Path.GetFullPath(path.Trim());
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
	internal static class InteractionAnimationAssetPathResolver
	{
		internal const string RootMissingReason = "pack_asset_root_missing";

		internal const string PathEscapesRootReason = "asset_bundle_path_escapes_root";

		internal static bool TryNormalizeAssetRoot(string assetRootPath, out string normalizedRoot, out string reason)
		{
			normalizedRoot = string.Empty;
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(assetRootPath))
			{
				reason = "pack_asset_root_missing";
				return false;
			}
			try
			{
				normalizedRoot = TrimEndingDirectorySeparators(Path.GetFullPath(assetRootPath.Trim()));
			}
			catch (Exception ex)
			{
				reason = "pack_asset_root_invalid:" + ex.GetType().Name;
				normalizedRoot = string.Empty;
				return false;
			}
			if (!Directory.Exists(normalizedRoot))
			{
				reason = "pack_asset_root_missing:" + normalizedRoot;
				normalizedRoot = string.Empty;
				return false;
			}
			return true;
		}

		internal static bool TryResolveBundlePath(string bundleFileName, string normalizedAssetRoot, out string resolvedPath, out string reason)
		{
			resolvedPath = string.Empty;
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(bundleFileName))
			{
				reason = "asset_bundle_file_empty";
				return false;
			}
			if (string.IsNullOrWhiteSpace(normalizedAssetRoot))
			{
				reason = "pack_asset_root_missing";
				return false;
			}
			try
			{
				string text = (Path.IsPathRooted(bundleFileName) ? Path.GetFullPath(bundleFileName) : Path.GetFullPath(Path.Combine(normalizedAssetRoot, bundleFileName)));
				if (!IsWithinRoot(normalizedAssetRoot, text))
				{
					reason = "asset_bundle_path_escapes_root:" + bundleFileName;
					return false;
				}
				resolvedPath = text;
				return true;
			}
			catch (Exception ex)
			{
				reason = "asset_bundle_path_invalid:" + ex.GetType().Name;
				return false;
			}
		}

		private static bool IsWithinRoot(string normalizedRoot, string candidate)
		{
			string text = TrimEndingDirectorySeparators(Path.GetFullPath(normalizedRoot));
			string fullPath = Path.GetFullPath(candidate);
			if (string.Equals(text, fullPath, StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			return fullPath.StartsWith(text + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
		}

		private static string TrimEndingDirectorySeparators(string path)
		{
			string text = Path.GetPathRoot(path) ?? string.Empty;
			while (path.Length > text.Length && (path[path.Length - 1] == Path.DirectorySeparatorChar || path[path.Length - 1] == Path.AltDirectorySeparatorChar))
			{
				path = path.Substring(0, path.Length - 1);
			}
			return path;
		}
	}
	internal delegate bool InteractionAnimationBodyOwnershipValidator(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, InteractionAnimationHandle[] conflicts, out string reason);
	internal sealed class InteractionAnimationCoordinator
	{
		private readonly ManualLogSource logger;

		private readonly Func<InteractionAnimationPresentationKind, IInteractionPresenter> presenterFactory;

		private readonly Func<PlayerControllerB> localPlayerResolver;

		private readonly InteractionAnimationBodyOwnershipValidator bodyOwnershipValidator;

		private readonly Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession> sessionFactory;

		private readonly Dictionary<string, RegisteredPackSnapshot> packs = new Dictionary<string, RegisteredPackSnapshot>(StringComparer.OrdinalIgnoreCase);

		private readonly Dictionary<InteractionAnimationHandle, InteractionAnimationSession> activeSessions = new Dictionary<InteractionAnimationHandle, InteractionAnimationSession>();

		private readonly InteractionAnimationResourceLeaseRegistry leases = new InteractionAnimationResourceLeaseRegistry();

		internal InteractionAnimationCoordinator(ManualLogSource logger, Func<InteractionAnimationPresentationKind, IInteractionPresenter> presenterFactory = null, Func<PlayerControllerB> localPlayerResolver = null, InteractionAnimationBodyOwnershipValidator bodyOwnershipValidator = null, Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession> sessionFactory = null)
		{
			this.logger = logger;
			this.presenterFactory = presenterFactory ?? new Func<InteractionAnimationPresentationKind, IInteractionPresenter>(CreateDefaultPresenter);
			this.localPlayerResolver = localPlayerResolver ?? new Func<PlayerControllerB>(ResolveDefaultLocalPlayer);
			this.bodyOwnershipValidator = bodyOwnershipValidator ?? new InteractionAnimationBodyOwnershipValidator(TryValidateBodyAnimatorOwnership);
			this.sessionFactory = sessionFactory ?? ((Func<InteractionAnimationContext, IInteractionPresenter, InteractionAnimationSession>)((InteractionAnimationContext context, IInteractionPresenter presenter) => new InteractionAnimationSession(context, presenter)));
		}

		internal bool TryRegisterInteractionPack(InteractionAnimationPackDefinition pack, out string reason)
		{
			RegisteredPackSnapshot snapshot;
			InteractionAnimationValidationReport interactionAnimationValidationReport = InteractionAnimationPackValidator.Validate(pack, out snapshot);
			reason = InteractionAnimationManifestValidator.GetFirstErrorCode(interactionAnimationValidationReport);
			if (!interactionAnimationValidationReport.IsValid)
			{
				return false;
			}
			if (packs.ContainsKey(snapshot.PackId))
			{
				reason = "pack_already_registered";
				return false;
			}
			packs.Add(snapshot.PackId, snapshot);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] pack.registered: pack='" + snapshot.PackId + "' version='" + snapshot.Version + "' " + $"interactions={snapshot.InteractionCount}."));
			}
			return true;
		}

		internal bool TryStartInteraction(InteractionAnimationRequest request, out InteractionAnimationHandle handle, out string reason)
		{
			handle = InteractionAnimationHandle.Empty;
			if (!TryResolveRequest(request, out var pack, out var interaction, out reason))
			{
				return false;
			}
			PlayerControllerB val = ResolveLocalPlayer();
			bool flag = request.Player == val;
			if (interaction.PresentationKind == InteractionAnimationPresentationKind.DedicatedLocalViewmodel && !flag)
			{
				reason = "dedicated_viewmodel_requires_local_player";
				return false;
			}
			InteractionAnimationResourceClaim[] claims = BuildClaims(request.Player, interaction.PresentationKind, flag);
			if (!leases.TryPlanAcquisition(claims, request.ConflictPolicy, out var conflicts, out reason))
			{
				return false;
			}
			if (!bodyOwnershipValidator(request.Player, interaction.PresentationKind, conflicts, out reason))
			{
				return false;
			}
			handle = InteractionAnimationHandle.NewHandle();
			InteractionAnimationRequest request2 = new InteractionAnimationRequest
			{
				Player = request.Player,
				PackId = pack.PackId,
				InteractionId = interaction.InteractionId,
				ConflictPolicy = request.ConflictPolicy
			};
			InteractionAnimationContext arg = new InteractionAnimationContext(handle, request2, interaction.CreateDefinition(), interaction.Manifest, pack.AssetRootPath, logger);
			IInteractionPresenter arg2 = CreatePresenter(interaction.PresentationKind);
			InteractionAnimationSession interactionAnimationSession = sessionFactory(arg, arg2);
			if (!interactionAnimationSession.TryPreflight(out reason))
			{
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			InteractionAnimationSession[] suspended = Array.Empty<InteractionAnimationSession>();
			if (conflicts.Length != 0 && !TrySuspendConflicts(conflicts, out suspended, out reason))
			{
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			if (!leases.TryAcquire(handle, claims, out reason))
			{
				ResumeConflicts(suspended);
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			if (!interactionAnimationSession.TryStart(out reason))
			{
				leases.Release(handle);
				ResumeConflicts(suspended);
				handle = InteractionAnimationHandle.Empty;
				return false;
			}
			FinalizeConflicts(suspended);
			activeSessions.Add(handle, interactionAnimationSession);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.started: " + $"handle={handle} pack='{pack.PackId}' interaction='{interaction.InteractionId}' " + $"presentation='{interaction.PresentationKind}'."));
			}
			return true;
		}

		internal bool TryPreloadInteractionAssets(string packId, string interactionId, out string reason)
		{
			reason = string.Empty;
			if (string.IsNullOrWhiteSpace(packId) || string.IsNullOrWhiteSpace(interactionId))
			{
				reason = "preload_invalid_identity";
				return false;
			}
			if (!packs.TryGetValue(packId, out var value))
			{
				reason = "pack_not_registered";
				return false;
			}
			if (!value.TryGetInteraction(interactionId, out var interaction))
			{
				reason = "interaction_not_registered";
				return false;
			}
			if (interaction.PresentationKind == InteractionAnimationPresentationKind.BodyWorld)
			{
				return LiveBodyAnimatorPresenter.TryPreloadBundles(interaction.Manifest, value.AssetRootPath, logger, out reason);
			}
			return LocalViewmodelPresenter.TryBeginPreload(interaction.Manifest, value.AssetRootPath, logger, out reason);
		}

		internal bool TryStopInteraction(InteractionAnimationHandle handle, InteractionAnimationStopReason reason)
		{
			if (!activeSessions.TryGetValue(handle, out var value))
			{
				return false;
			}
			if (!value.TryStopAndRestore(reason))
			{
				return false;
			}
			leases.Release(handle);
			activeSessions.Remove(handle);
			NotifyEnded(value, reason);
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.stopped: " + $"handle={handle} reason='{reason}'."));
			}
			return true;
		}

		internal bool IsInteractionActive(InteractionAnimationHandle handle)
		{
			if (activeSessions.TryGetValue(handle, out var value))
			{
				return value.IsActive;
			}
			return false;
		}

		internal bool TryGetActiveInteraction(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, out InteractionAnimationHandle handle)
		{
			handle = InteractionAnimationHandle.Empty;
			if (player == null)
			{
				return false;
			}
			foreach (KeyValuePair<InteractionAnimationHandle, InteractionAnimationSession> activeSession in activeSessions)
			{
				if (activeSession.Value.IsActive && activeSession.Value.Player == player && activeSession.Value.PresentationKind == presentationKind)
				{
					handle = activeSession.Key;
					return true;
				}
			}
			return false;
		}

		internal bool TrySetInteractionAnimatorParameter(InteractionAnimationHandle handle, string parameterName, AnimatorControllerParameterType parameterType, float value)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (activeSessions.TryGetValue(handle, out var value2))
			{
				return value2.TrySetAnimatorParameter(parameterName, parameterType, value);
			}
			return false;
		}

		internal bool TryBeginInteractionExit(InteractionAnimationHandle handle, out string reason)
		{
			reason = string.Empty;
			if (!activeSessions.TryGetValue(handle, out var value) || !value.IsActive)
			{
				reason = "interaction_not_active";
				return false;
			}
			float num = value.BeginExit();
			ManualLogSource obj = logger;
			if (obj != null)
			{
				obj.LogDebug((object)("[LCInteractionAnimationAPI] interaction.exit_begun: " + $"handle={handle} exitSeconds={num:0.###}."));
			}
			return true;
		}

		internal void Tick(float deltaTime)
		{
			if (activeSessions.Count == 0)
			{
				return;
			}
			InteractionAnimationHandle[] array = activeSessions.Keys.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (activeSessions.TryGetValue(array[i], out var value))
				{
					InteractionAnimationStopReason? interactionAnimationStopReason = value.Tick(deltaTime);
					if (interactionAnimationStopReason.HasValue)
					{
						TryStopInteraction(array[i], interactionAnimationStopReason.Value);
					}
				}
			}
		}

		internal void Shutdown()
		{
			InteractionAnimationHandle[] array = activeSessions.Keys.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				TryStopInteraction(array[i], InteractionAnimationStopReason.Shutdown);
			}
			leases.Clear();
			packs.Clear();
		}

		private bool TryResolveRequest(InteractionAnimationRequest request, out RegisteredPackSnapshot pack, out RegisteredInteractionSnapshot interaction, out string reason)
		{
			pack = null;
			interaction = null;
			reason = string.Empty;
			if (request == null)
			{
				reason = "request_null";
				return false;
			}
			if (request.Player == null)
			{
				reason = "request_player_missing";
				return false;
			}
			if (string.IsNullOrWhiteSpace(request.PackId))
			{
				reason = "request_pack_id_empty";
				return false;
			}
			if (string.IsNullOrWhiteSpace(request.InteractionId))
			{
				reason = "request_interaction_id_empty";
				return false;
			}
			if (!Enum.IsDefined(typeof(InteractionAnimationConflictPolicy), request.ConflictPolicy))
			{
				reason = "request_conflict_policy_invalid";
				return false;
			}
			if (!packs.TryGetValue(request.PackId, out pack))
			{
				reason = "pack_not_registered";
				return false;
			}
			if (!pack.TryGetInteraction(request.InteractionId, out interaction))
			{
				reason = "interaction_not_registered";
				return false;
			}
			return true;
		}

		private bool TryValidateBodyAnimatorOwnership(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, InteractionAnimationHandle[] conflicts, out string reason)
		{
			reason = string.Empty;
			if (presentationKind != InteractionAnimationPresentationKind.BodyWorld)
			{
				return true;
			}
			Animator val = (((Object)(object)player != (Object)null) ? player.playerBodyAnimator : null);
			if ((Object)(object)val == (Object)null)
			{
				reason = "missing_body_animator";
				return false;
			}
			for (int i = 0; i < conflicts.Length; i++)
			{
				if (activeSessions.TryGetValue(conflicts[i], out var value) && value.Player == player && value.PresentationKind == InteractionAnimationPresentationKind.BodyWorld && value.HasResourceOwnership)
				{
					return true;
				}
			}
			RuntimeAnimatorController val2 = ResolveExpectedVanillaController(player);
			if ((Object)(object)val2 == (Object)null)
			{
				reason = "expected_player_animator_controller_missing";
				return false;
			}
			if ((Object)(object)val.runtimeAnimatorController != (Object)(object)val2)
			{
				reason = "player_animator_owned_externally";
				return false;
			}
			return true;
		}

		private bool TrySuspendConflicts(InteractionAnimationHandle[] handles, out InteractionAnimationSession[] suspended, out string reason)
		{
			reason = string.Empty;
			List<InteractionAnimationSession> list = new List<InteractionAnimationSession>();
			for (int i = 0; i < handles.Length; i++)
			{
				if (!activeSessions.TryGetValue(handles[i], out var value))
				{
					continue;
				}
				if (!value.TrySuspend(out reason))
				{
					for (int j = 0; j < list.Count; j++)
					{
						InteractionAnimationSession interactionAnimationSession = list[j];
						if (!interactionAnimationSession.TryResume(out var _))
						{
							leases.Release(interactionAnimationSession.Handle);
							activeSessions.Remove(interactionAnimationSession.Handle);
							interactionAnimationSession.TryStopAndRestore(InteractionAnimationStopReason.PresenterFailure);
							NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.PresenterFailure);
						}
					}
					if (value.IsEnded)
					{
						leases.Release(value.Handle);
						activeSessions.Remove(value.Handle);
						NotifyEnded(value, InteractionAnimationStopReason.PresenterFailure);
					}
					suspended = Array.Empty<InteractionAnimationSession>();
					return false;
				}
				list.Add(value);
			}
			suspended = list.ToArray();
			for (int k = 0; k < suspended.Length; k++)
			{
				leases.Release(suspended[k].Handle);
			}
			return true;
		}

		private void ResumeConflicts(InteractionAnimationSession[] sessions)
		{
			foreach (InteractionAnimationSession interactionAnimationSession in sessions)
			{
				bool isLocal = interactionAnimationSession.Player == ResolveLocalPlayer();
				InteractionAnimationResourceClaim[] claims = BuildClaims(interactionAnimationSession.Player, interactionAnimationSession.PresentationKind, isLocal);
				if (!leases.TryAcquire(interactionAnimationSession.Handle, claims, out var reason) || !interactionAnimationSession.TryResume(out reason))
				{
					leases.Release(interactionAnimationSession.Handle);
					activeSessions.Remove(interactionAnimationSession.Handle);
					interactionAnimationSession.TryStopAndRestore(InteractionAnimationStopReason.PresenterFailure);
					NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.PresenterFailure);
				}
			}
		}

		private void FinalizeConflicts(InteractionAnimationSession[] sessions)
		{
			foreach (InteractionAnimationSession interactionAnimationSession in sessions)
			{
				activeSessions.Remove(interactionAnimationSession.Handle);
				if (interactionAnimationSession.TryFinalizeSuspended())
				{
					NotifyEnded(interactionAnimationSession, InteractionAnimationStopReason.Interrupted);
				}
			}
		}

		private void NotifyEnded(InteractionAnimationSession session, InteractionAnimationStopReason reason)
		{
			LCInteractionAnimationAPI.NotifyInteractionEnded(session.CreateEndedEvent(reason));
		}

		private static InteractionAnimationResourceClaim[] BuildClaims(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, bool isLocal)
		{
			if (presentationKind != InteractionAnimationPresentationKind.DedicatedLocalViewmodel)
			{
				if (!isLocal)
				{
					return new InteractionAnimationResourceClaim[1]
					{
						new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.BodyAnimator, player)
					};
				}
				return new InteractionAnimationResourceClaim[2]
				{
					new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.BodyAnimator, player),
					new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.LocalCameraAndArms, player)
				};
			}
			return new InteractionAnimationResourceClaim[1]
			{
				new InteractionAnimationResourceClaim(InteractionAnimationResourceKind.LocalCameraAndArms, player)
			};
		}

		private PlayerControllerB ResolveLocalPlayer()
		{
			return localPlayerResolver();
		}

		private static PlayerControllerB ResolveDefaultLocalPlayer()
		{
			try
			{
				return GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController;
			}
			catch
			{
				return null;
			}
		}

		private RuntimeAnimatorController ResolveExpectedVanillaController(PlayerControllerB player)
		{
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || player == null)
			{
				return null;
			}
			if (player != ResolveLocalPlayer())
			{
				return instance.otherClientsAnimatorController;
			}
			return instance.localClientAnimatorController;
		}

		private IInteractionPresenter CreatePresenter(InteractionAnimationPresentationKind presentationKind)
		{
			return presenterFactory(presentationKind);
		}

		private static IInteractionPresenter CreateDefaultPresenter(InteractionAnimationPresentationKind presentationKind)
		{
			return presentationKind switch
			{
				InteractionAnimationPresentationKind.DedicatedLocalViewmodel => new LocalViewmodelPresenter(), 
				InteractionAnimationPresentationKind.BodyWorld => new LiveBodyAnimatorPresenter(), 
				_ => null, 
			};
		}
	}
	internal sealed class RegisteredPackSnapshot
	{
		private readonly Dictionary<string, RegisteredInteractionSnapshot> interactions;

		internal string PackId { get; }

		internal string Version { get; }

		internal string AssetRootPath { get; }

		internal int InteractionCount => interactions.Count;

		internal RegisteredPackSnapshot(string packId, string version, string assetRootPath, Dictionary<string, RegisteredInteractionSnapshot> interactions)
		{
			PackId = packId;
			Version = version;
			AssetRootPath = assetRootPath;
			this.interactions = interactions;
		}

		internal bool TryGetInteraction(string interactionId, out RegisteredInteractionSnapshot interaction)
		{
			return interactions.TryGetValue(interactionId, out interaction);
		}
	}
	internal sealed class RegisteredInteractionSnapshot
	{
		internal string InteractionId { get; }

		internal InteractionAnimationPresentationKind PresentationKind { get; }

		internal string ManifestJson { get; }

		internal InteractionAnimationManifest Manifest { get; }

		internal RegisteredInteractionSnapshot(string interactionId, InteractionAnimationPresentationKind presentationKind, string manifestJson, InteractionAnimationManifest manifest)
		{
			InteractionId = interactionId;
			PresentationKind = presentationKind;
			ManifestJson = manifestJson;
			Manifest = manifest;
		}

		internal InteractionAnimationDefinition CreateDefinition()
		{
			return new InteractionAnimationDefinition
			{
				InteractionId = InteractionId,
				PresentationKind = PresentationKind,
				ManifestJson = ManifestJson
			};
		}
	}
	internal static class InteractionAnimationPackValidator
	{
		internal static InteractionAnimationValidationReport Validate(InteractionAnimationPackDefinition pack, out RegisteredPackSnapshot snapshot)
		{
			snapshot = null;
			List<InteractionAnimationValidationIssue> issues = new List<InteractionAnimationValidationIssue>();
			if (pack == null)
			{
				AddError(issues, "pack_null", "$", "Pack definition is required.");
				return new InteractionAnimationValidationReport(issues);
			}
			RequireValue(pack.PackId, "$.PackId", "pack_id_empty", issues);
			RequireValue(pack.Version, "$.Version", "pack_version_empty", issues);
			string normalizedRoot = string.Empty;
			if (!InteractionAnimationAssetPathResolver.TryNormalizeAssetRoot(pack.AssetRootPath, out normalizedRoot, out var reason))
			{
				AddError(issues, ReasonCode(reason), "$.AssetRootPath", "AssetRootPath must name an existing directory and is required for path confinement.");
			}
			Dictionary<string, RegisteredInteractionSnapshot> interactions = new Dictionary<string, RegisteredInteractionSnapshot>(StringComparer.OrdinalIgnoreCase);
			if (pack.Interactions == null || pack.Interactions.Length == 0)
			{
				AddError(issues, "pack_interactions_empty", "$.Interactions", "At least one interaction is required.");
			}
			else
			{
				for (int i = 0; i < pack.Interactions.Length; i++)
				{
					ValidateInteraction(pack.Interactions[i], i, interactions, issues);
				}
			}
			InteractionAnimationValidationReport interactionAnimationValidationReport = new InteractionAnimationValidationReport(issues);
			if (interactionAnimationValidationReport.IsValid)
			{
				snapshot = new RegisteredPackSnapshot(pack.PackId, pack.Version, normalizedRoot, interactions);
			}
			return interactionAnimationValidationReport;
		}

		private static void ValidateInteraction(InteractionAnimationDefinition definition, int index, IDictionary<string, RegisteredInteractionSnapshot> interactions, IList<InteractionAnimationValidationIssue> issues)
		{
			string text = "$.Interactions[" + index + "]";
			if (definition == null)
			{
				AddError(issues, "interaction_null", text, "Interaction is required.");
				return;
			}
			RequireValue(definition.InteractionId, text + ".InteractionId", "interaction_id_empty", issues);
			if (!Enum.IsDefined(typeof(InteractionAnimationPresentationKind), definition.PresentationKind))
			{
				AddError(issues, "presentation_kind_invalid", text + ".PresentationKind", "Only BodyWorld and DedicatedLocalViewmodel are supported.");
			}
			InteractionAnimationManifest manifest;
			InteractionAnimationValidationReport interactionAnimationValidationReport = InteractionAnimationManifestValidator.Validate(definition.ManifestJson, definition.InteractionId, definition.PresentationKind, out manifest);
			for (int i = 0; i < interactionAnimationValidationReport.Issues.Count; i++)
			{
				InteractionAnimationValidationIssue interactionAnimationValidationIssue = interactionAnimationValidationReport.Issues[i];
				issues.Add(new InteractionAnimationValidationIssue(interactionAnimationValidationIssue.Code, text + ".ManifestJson" + interactionAnimationValidationIssue.JsonPath.Substring(1), interactionAnimationValidationIssue.Message, interactionAnimationValidationIssue.Severity));
			}
			if (!string.IsNullOrWhiteSpace(definition.InteractionId))
			{
				if (interactions.ContainsKey(definition.InteractionId))
				{
					AddError(issues, "interaction_id_duplicate", text + ".InteractionId", "Interaction ids must be unique within a pack.");
				}
				else if (interactionAnimationValidationReport.IsValid && manifest != null)
				{
					interactions.Add(definition.InteractionId, new RegisteredInteractionSnapshot(definition.InteractionId, definition.PresentationKind, definition.ManifestJson ?? string.Empty, manifest));
				}
			}
		}

		private static void RequireValue(string value, string path, string code, IList<InteractionAnimationValidationIssue> issues)
		{
			if (string.IsNullOrWhiteSpace(value) || value != value.Trim())
			{
				AddError(issues, code, path, "A trimmed non-empty value is required.");
			}
		}

		private static string ReasonCode(string reason)
		{
			if (string.IsNullOrWhiteSpace(reason))
			{
				return "pack_asset_root_invalid";
			}
			int num = reason.IndexOf(':');
			if (num < 0)
			{
				return reason;
			}
			return reason.Substring(0, num);
		}

		private static void AddError(IList<InteractionAnimationValidationIssue> issues, string code, string path, string message)
		{
			issues.Add(new InteractionAnimationValidationIssue(code, path, message, InteractionAnimationValidationSeverity.Error));
		}
	}
	internal enum InteractionAnimationResourceKind
	{
		BodyAnimator,
		LocalCameraAndArms
	}
	internal readonly struct InteractionAnimationResourceClaim : IEquatable<InteractionAnimationResourceClaim>
	{
		internal InteractionAnimationResourceKind Kind { get; }

		internal object Owner { get; }

		internal InteractionAnimationResourceClaim(InteractionAnimationResourceKind kind, object owner)
		{
			Kind = kind;
			Owner = owner;
		}

		public bool Equals(InteractionAnimationResourceClaim other)
		{
			if (Kind == other.Kind)
			{
				return Owner == other.Owner;
			}
			return false;
		}

		public override bool Equals(object obj)
		{
			if (obj is InteractionAnimationResourceClaim other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return ((int)Kind * 397) ^ ((Owner != null) ? RuntimeHelpers.GetHashCode(Owner) : 0);
		}
	}
	internal sealed class InteractionAnimationResourceLeaseRegistry
	{
		private readonly Dictionary<InteractionAnimationResourceClaim, InteractionAnimationHandle> owners = new Dictionary<InteractionAnimationResourceClaim, InteractionAnimationHandle>();

		private readonly Dictionary<InteractionAnimationHandle, InteractionAnimationResourceClaim[]> claimsByHandle = new Dictionary<InteractionAnimationHandle, InteractionAnimationResourceClaim[]>();

		internal bool TryPlanAcquisition(InteractionAnimationResourceClaim[] claims, InteractionAnimationConflictPolicy policy, out InteractionAnimationHandle[] conflicts, out string reason)
		{
			reason = string.Empty;
			HashSet<InteractionAnimationHandle> hashSet = new HashSet<InteractionAnimationHandle>();
			claims = claims ?? Array.Empty<InteractionAnimationResourceClaim>();
			for (int i = 0; i < claims.Length; i++)
			{
				if (claims[i].Owner == null)
				{
					conflicts = Array.Empty<InteractionAnimationHandle>();
					reason = "interaction_resource_owner_missing";
					return false;
				}
				if (owners.TryGetValue(claims[i], out var value))
				{
					hashSet.Add(value);
				}
			}
			conflicts = new InteractionAnimationHandle[hashSet.Count];
			hashSet.CopyTo(conflicts);
			if (conflicts.Length != 0 && policy == InteractionAnimationConflictPolicy.RejectIfBusy)
			{
				reason = "interaction_resource_busy";
				return false;
			}
			return true;
		}

		internal bool TryAcquire(InteractionAnimationHandle handle, InteractionAnimationResourceClaim[] claims, out string reason)
		{
			reason = string.Empty;
			if (!handle.IsValid || claimsByHandle.ContainsKey(handle))
			{
				reason = "interaction_lease_handle_invalid";
				return false;
			}
			claims = claims ?? Array.Empty<InteractionAnimationResourceClaim>();
			for (int i = 0; i < claims.Length; i++)
			{
				if (claims[i].Owner == null || owners.ContainsKey(claims[i]))
				{
					reason = "interaction_resource_busy";
					return false;
				}
			}
			InteractionAnimationResourceClaim[] array = new InteractionAnimationResourceClaim[claims.Length];
			Array.Copy(claims, array, claims.Length);
			claimsByHandle.Add(handle, array);
			for (int j = 0; j < array.Length; j++)
			{
				owners.Add(array[j], handle);
			}
			return true;
		}

		internal void Release(InteractionAnimationHandle handle)
		{
			if (!claimsByHandle.TryGetValue(handle, out var value))
			{
				return;
			}
			claimsByHandle.Remove(handle);
			for (int i = 0; i < value.Length; i++)
			{
				if (owners.TryGetValue(value[i], out var value2) && value2 == handle)
				{
					owners.Remove(value[i]);
				}
			}
		}

		internal bool IsOwned(InteractionAnimationResourceKind kind, object owner, out InteractionAnimationHandle handle)
		{
			return owners.TryGetValue(new InteractionAnimationResourceClaim(kind, owner), out handle);
		}

		internal void Clear()
		{
			owners.Clear();
			claimsByHandle.Clear();
		}
	}
	internal sealed class InteractionAnimationSession
	{
		private readonly InteractionAnimationContext context;

		private readonly IInteractionPresenter presenter;

		private readonly StartOfRound owningRound;

		private readonly bool wasPlayerControlled;

		private readonly Func<DateTime> utcNow;

		private readonly Func<InteractionAnimationStopReason?> invalidationResolver;

		private DateTime startedUtc;

		private DateTime exitStopAtUtc = DateTime.MaxValue;

		private bool active;

		private bool suspended;

		private bool ended;

		internal InteractionAnimationHandle Handle => context.Handle;

		internal PlayerControllerB Player => context.Request.Player;

		internal string PackId => context.Request.PackId;

		internal string InteractionId => context.Request.InteractionId;

		internal InteractionAnimationPresentationKind PresentationKind => context.Definition.PresentationKind;

		internal bool IsActive
		{
			get
			{
				if (active)
				{
					return !ended;
				}
				return false;
			}
		}

		internal bool IsSuspended
		{
			get
			{
				if (suspended)
				{
					return !ended;
				}
				return false;
			}
		}

		internal bool IsEnded => ended;

		internal bool HasResourceOwnership
		{
			get
			{
				if (active)
				{
					return presenter.HasResourceOwnership;
				}
				return false;
			}
		}

		internal InteractionAnimationSession(InteractionAnimationContext context, IInteractionPresenter presenter, Func<DateTime> utcNow = null, Func<InteractionAnimationStopReason?> invalidationResolver = null)
		{
			this.context = context;
			this.presenter = presenter;
			this.utcNow = utcNow ?? ((Func<DateTime>)(() => DateTime.UtcNow));
			this.invalidationResolver = invalidationResolver ?? new Func<InteractionAnimationStopReason?>(GetInvalidationReason);
			try
			{
				owningRound = StartOfRound.Instance;
			}
			catch
			{
				owningRound = null;
			}
			try
			{
				wasPlayerControlled = context != null && context.Request?.Player?.isPlayerControlled == true;
			}
			catch
			{
				wasPlayerControlled = false;
			}
		}

		internal bool TryPreflight(out string reason)
		{
			reason = string.Empty;
			try
			{
				if (presenter == null)
				{
					reason = "presenter_missing";
					return false;
				}
				return presenter.TryPreflight(context, out reason);
			}
			catch (Exception ex)
			{
				reason = "presenter_preflight_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.preflight_failed: " + ex));
				}
				return false;
			}
		}

		internal bool TryStart(out string reason)
		{
			reason = string.Empty;
			try
			{
				if (presenter == null)
				{
					reason = "presenter_missing";
					return false;
				}
				if (!presenter.TryStart(context, out reason))
				{
					TryRestore(InteractionAnimationStopReason.PresenterFailure);
					return false;
				}
				startedUtc = utcNow();
				exitStopAtUtc = DateTime.MaxValue;
				active = true;
				suspended = false;
				return true;
			}
			catch (Exception ex)
			{
				reason = "presenter_start_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.start_failed: " + ex));
				}
				TryRestore(InteractionAnimationStopReason.PresenterFailure);
				return false;
			}
		}

		internal bool TrySuspend(out string reason)
		{
			reason = string.Empty;
			if (!active || ended)
			{
				return false;
			}
			try
			{
				presenter.Stop(InteractionAnimationStopReason.Interrupted);
				active = false;
				suspended = true;
				return true;
			}
			catch (Exception ex)
			{
				active = false;
				suspended = false;
				TryRestore(InteractionAnimationStopReason.PresenterFailure);
				ended = true;
				reason = "presenter_suspend_exception:" + ex.GetType().Name;
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.suspend_failed: " + ex));
				}
				return false;
			}
		}

		internal bool TryResume(out string reason)
		{
			reason = string.Empty;
			if (!suspended || ended)
			{
				return false;
			}
			DateTime dateTime = startedUtc;
			DateTime dateTime2 = exitStopAtUtc;
			if (!TryPreflight(out reason) || !TryStart(out reason))
			{
				return false;
			}
			startedUtc = dateTime;
			exitStopAtUtc = dateTime2;
			return true;
		}

		internal bool TryFinalizeSuspended()
		{
			if (!suspended || ended)
			{
				return false;
			}
			suspended = false;
			ended = true;
			return true;
		}

		internal bool TryStopAndRestore(InteractionAnimationStopReason reason)
		{
			if (ended)
			{
				return false;
			}
			if (active)
			{
				TryRestore(reason);
			}
			active = false;
			suspended = false;
			ended = true;
			return true;
		}

		internal InteractionAnimationStopReason? Tick(float deltaTime)
		{
			if (!active || ended)
			{
				return null;
			}
			InteractionAnimationStopReason? result = invalidationResolver();
			if (result.HasValue)
			{
				return result;
			}
			try
			{
				presenter.Tick(deltaTime);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.tick_failed: " + ex));
				}
				return InteractionAnimationStopReason.PresenterFailure;
			}
			if (presenter.RequestedStopReason.HasValue)
			{
				return presenter.RequestedStopReason;
			}
			DateTime dateTime = utcNow();
			if (dateTime >= exitStopAtUtc)
			{
				return InteractionAnimationStopReason.NaturalEnd;
			}
			float durationSeconds = context.Manifest.durationSeconds;
			if (durationSeconds > 0f && (dateTime - startedUtc).TotalSeconds >= (double)durationSeconds)
			{
				return InteractionAnimationStopReason.NaturalEnd;
			}
			return null;
		}

		internal float BeginExit()
		{
			if (!active || presenter == null)
			{
				return 0f;
			}
			float num = Math.Max(0f, presenter.BeginExit());
			exitStopAtUtc = utcNow().AddSeconds(num);
			return num;
		}

		internal bool TrySetAnimatorParameter(string parameterName, AnimatorControllerParameterType parameterType, float value)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (active && presenter != null)
			{
				return presenter.TrySetAnimatorParameter(parameterName, parameterType, value);
			}
			return false;
		}

		internal InteractionAnimationEndedEventArgs CreateEndedEvent(InteractionAnimationStopReason reason)
		{
			return new InteractionAnimationEndedEventArgs(Handle, Player, PackId, InteractionId, PresentationKind, reason);
		}

		private InteractionAnimationStopReason? GetInvalidationReason()
		{
			//IL_0024: 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)
			PlayerControllerB player = Player;
			try
			{
				if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).gameObject == (Object)null)
				{
					goto IL_0033;
				}
				Scene scene = ((Component)player).gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					goto IL_0033;
				}
				if (player.isPlayerDead)
				{
					return InteractionAnimationStopReason.PlayerDied;
				}
				if (wasPlayerControlled && !player.isPlayerControlled)
				{
					return InteractionAnimationStopReason.PlayerInvalidated;
				}
				if ((Object)(object)owningRound != (Object)null && (Object)(object)StartOfRound.Instance != (Object)(object)owningRound)
				{
					return InteractionAnimationStopReason.RoundUnloaded;
				}
				goto end_IL_0007;
				IL_0033:
				return InteractionAnimationStopReason.PlayerInvalidated;
				end_IL_0007:;
			}
			catch
			{
				return InteractionAnimationStopReason.PlayerInvalidated;
			}
			return null;
		}

		private void TryRestore(InteractionAnimationStopReason reason)
		{
			try
			{
				presenter?.Stop(reason);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = context.Logger;
				if (logger != null)
				{
					logger.LogWarning((object)("[LCInteractionAnimationAPI] presenter.restore_failed: " + ex));
				}
			}
		}
	}
	public enum InteractionAnimationPresentationKind
	{
		DedicatedLocalViewmodel,
		BodyWorld
	}
	public enum InteractionAnimationConflictPolicy
	{
		RejectIfBusy,
		InterruptExisting
	}
	public enum InteractionAnimationStopReason
	{
		Requested,
		NaturalEnd,
		Interrupted,
		PlayerInvalidated,
		PlayerDied,
		RoundUnloaded,
		PresenterFailure,
		Shutdown
	}
	public readonly struct InteractionAnimationHandle : IEquatable<InteractionAnimationHandle>
	{
		private readonly Guid value;

		public static InteractionAnimationHandle Empty => new InteractionAnimationHandle(Guid.Empty);

		public bool IsValid => value != Guid.Empty;

		private InteractionAnimationHandle(Guid value)
		{
			this.value = value;
		}

		internal static InteractionAnimationHandle NewHandle()
		{
			return new InteractionAnimationHandle(Guid.NewGuid());
		}

		public bool Equals(InteractionAnimationHandle other)
		{
			Guid guid = value;
			return guid.Equals(other.value);
		}

		public override bool Equals(object obj)
		{
			if (obj is InteractionAnimationHandle other)
			{
				return Equals(other);
			}
			return false;
		}

		public override int GetHashCode()
		{
			return value.GetHashCode();
		}

		public override string ToString()
		{
			return value.ToString();
		}

		public static bool operator ==(InteractionAnimationHandle left, InteractionAnimationHandle right)
		{
			return left.Equals(right);
		}

		public static bool operator !=(InteractionAnimationHandle left, InteractionAnimationHandle right)
		{
			return !left.Equals(right);
		}
	}
	public sealed class InteractionAnimationPackDefinition
	{
		public string PackId { get; set; } = string.Empty;

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

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

		public InteractionAnimationDefinition[] Interactions { get; set; } = Array.Empty<InteractionAnimationDefinition>();
	}
	public sealed class InteractionAnimationDefinition
	{
		public string InteractionId { get; set; } = string.Empty;

		public InteractionAnimationPresentationKind PresentationKind { get; set; }

		public string ManifestJson { get; set; } = string.Empty;
	}
	public sealed class InteractionAnimationRequest
	{
		public PlayerControllerB Player { get; set; }

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

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

		public InteractionAnimationConflictPolicy ConflictPolicy { get; set; }
	}
	public enum InteractionAnimationValidationSeverity
	{
		Warning,
		Error
	}
	public sealed class InteractionAnimationValidationIssue
	{
		public string Code { get; }

		public string JsonPath { get; }

		public string Message { get; }

		public InteractionAnimationValidationSeverity Severity { get; }

		internal InteractionAnimationValidationIssue(string code, string jsonPath, string message, InteractionAnimationValidationSeverity severity)
		{
			Code = code ?? string.Empty;
			JsonPath = jsonPath ?? "$";
			Message = message ?? string.Empty;
			Severity = severity;
		}
	}
	public sealed class InteractionAnimationValidationReport
	{
		private readonly ReadOnlyCollection<InteractionAnimationValidationIssue> issues;

		public bool IsValid
		{
			get
			{
				for (int i = 0; i < issues.Count; i++)
				{
					if (issues[i].Severity == InteractionAnimationValidationSeverity.Error)
					{
						return false;
					}
				}
				return true;
			}
		}

		public IReadOnlyList<InteractionAnimationValidationIssue> Issues => issues;

		internal InteractionAnimationValidationReport(IList<InteractionAnimationValidationIssue> issues)
		{
			this.issues = new ReadOnlyCollection<InteractionAnimationValidationIssue>(new List<InteractionAnimationValidationIssue>(issues ?? Array.Empty<InteractionAnimationValidationIssue>()));
		}
	}
	public sealed class InteractionAnimationEndedEventArgs : EventArgs
	{
		public InteractionAnimationHandle Handle { get; }

		public PlayerControllerB Player { get; }

		public string PackId { get; }

		public string InteractionId { get; }

		public InteractionAnimationPresentationKind PresentationKind { get; }

		public InteractionAnimationStopReason StopReason { get; }

		internal InteractionAnimationEndedEventArgs(InteractionAnimationHandle handle, PlayerControllerB player, string packId, string interactionId, InteractionAnimationPresentationKind presentationKind, InteractionAnimationStopReason stopReason)
		{
			Handle = handle;
			Player = player;
			PackId = packId ?? string.Empty;
			InteractionId = interactionId ?? string.Empty;
			PresentationKind = presentationKind;
			StopReason = stopReason;
		}
	}
	internal sealed class InteractionAnimationContext
	{
		internal InteractionAnimationHandle Handle { get; }

		internal InteractionAnimationRequest Request { get; }

		internal InteractionAnimationDefinition Definition { get; }

		internal InteractionAnimationManifest Manifest { get; }

		internal string AssetRootPath { get; }

		internal ManualLogSource Logger { get; }

		internal InteractionAnimationContext(InteractionAnimationHandle handle, InteractionAnimationRequest request, InteractionAnimationDefinition definition, InteractionAnimationManifest manifest, string assetRootPath, ManualLogSource logger)
		{
			Handle = handle;
			Request = request;
			Definition = definition;
			Manifest = manifest;
			AssetRootPath = assetRootPath ?? string.Empty;
			Logger = logger;
		}
	}
	public static class LCInteractionAnimationAPI
	{
		private static InteractionAnimationCoordinator coordinator;

		public static bool IsInitialized => coordinator != null;

		public static event EventHandler<InteractionAnimationEndedEventArgs> InteractionEnded;

		public static InteractionAnimationValidationReport ValidateInteractionPack(InteractionAnimationPackDefinition pack)
		{
			RegisteredPackSnapshot snapshot;
			return InteractionAnimationPackValidator.Validate(pack, out snapshot);
		}

		public static InteractionAnimationValidationReport ValidateInteractionManifest(string manifestJson, string expectedInteractionId, InteractionAnimationPresentationKind presentationKind)
		{
			InteractionAnimationManifest manifest;
			return InteractionAnimationManifestValidator.Validate(manifestJson, expectedInteractionId, presentationKind, out manifest);
		}

		public static bool TryRegisterInteractionPack(InteractionAnimationPackDefinition pack, out string reason)
		{
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryRegisterInteractionPack(pack, out reason);
		}

		public static bool TryStartInteraction(InteractionAnimationRequest request, out InteractionAnimationHandle handle, out string reason)
		{
			handle = InteractionAnimationHandle.Empty;
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryStartInteraction(request, out handle, out reason);
		}

		public static bool TryPreloadInteractionAssets(string packId, string interactionId, out string reason)
		{
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryPreloadInteractionAssets(packId, interactionId, out reason);
		}

		public static bool TryStopInteraction(InteractionAnimationHandle handle, InteractionAnimationStopReason stopReason)
		{
			if (coordinator != null)
			{
				return coordinator.TryStopInteraction(handle, stopReason);
			}
			return false;
		}

		public static bool IsInteractionActive(InteractionAnimationHandle handle)
		{
			if (coordinator != null)
			{
				return coordinator.IsInteractionActive(handle);
			}
			return false;
		}

		public static bool TryGetActiveInteraction(PlayerControllerB player, InteractionAnimationPresentationKind presentationKind, out InteractionAnimationHandle handle)
		{
			handle = InteractionAnimationHandle.Empty;
			if (coordinator != null)
			{
				return coordinator.TryGetActiveInteraction(player, presentationKind, out handle);
			}
			return false;
		}

		public static bool TrySetInteractionBool(InteractionAnimationHandle handle, string parameterName, bool value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)4, value ? 1f : 0f);
			}
			return false;
		}

		public static bool TrySetInteractionInt(InteractionAnimationHandle handle, string parameterName, int value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)3, value);
			}
			return false;
		}

		public static bool TrySetInteractionFloat(InteractionAnimationHandle handle, string parameterName, float value)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)1, value);
			}
			return false;
		}

		public static bool TryFireInteractionTrigger(InteractionAnimationHandle handle, string parameterName)
		{
			if (coordinator != null)
			{
				return coordinator.TrySetInteractionAnimatorParameter(handle, parameterName, (AnimatorControllerParameterType)9, 0f);
			}
			return false;
		}

		public static bool TryBeginInteractionExit(InteractionAnimationHandle handle, out string reason)
		{
			reason = string.Empty;
			if (coordinator == null)
			{
				reason = "interaction_animation_api_not_initialized";
				return false;
			}
			return coordinator.TryBeginInteractionExit(handle, out reason);
		}

		internal static void Initialize(InteractionAnimationCoordinator value)
		{
			coordinator = value;
		}

		internal static void NotifyInteractionEnded(InteractionAnimationEndedEventArgs args)
		{
			Delegate[] array = LCInteractionAnimationAPI.InteractionEnded?.GetInvocationList();
			if (array == null)
			{
				return;
			}
			for (int i = 0; i < array.Length; i++)
			{
				try
				{
					((EventHandler<InteractionAnimationEndedEventArgs>)array[i])(null, args);
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[LCInteractionAnimationAPI] interaction_ended_handler_failed: " + ex));
					}
				}
			}
		}

		internal static void Shutdown()
		{
			coordinator = null;
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB), "UpdatePlayerAnimationsToOtherClients")]
	internal static class PlayerAnimationSyncStateGuardPatch
	{
		[HarmonyPrefix]
		private static void EnsureAnimationStateHashCounts(PlayerControllerB __instance, ref List<int> ___currentAnimationStateHash, ref List<int> ___previousAnimationStateHash)
		{
			int? obj;
			if (__instance == null)
			{
				obj = null;
			}
			else
			{
				Animator playerBodyAnimator = __instance.playerBodyAnimator;
				obj = ((playerBodyAnimator != null) ? new int?(playerBodyAnimator.layerCount) : ((int?)null));
			}
			int? num = obj;
			int valueOrDefault = num.GetValueOrDefault();
			bool num2 = EnsureCount(ref ___currentAnimationStateHash, valueOrDefault);
			bool flag = EnsureCount(ref ___previousAnimationStateHash, valueOrDefault);
			if (num2 || flag)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)("[LCInteractionAnimationAPI] live_body.sync_state_capacity_expanded: " + $"player={__instance.playerClientId}, layers={valueOrDefault}."));
				}
			}
		}

		internal static bool EnsureCount(ref List<int> states, int requiredCount)
		{
			if (requiredCount > 0)
			{
				List<int> obj = states;
				if (obj == null || obj.Count < requiredCount)
				{
					if (states == null)
					{
						states = new List<int>(requiredCount);
					}
					while (states.Count < requiredCount)
					{
						states.Add(0);
					}
					return true;
				}
			}
			return false;
		}
	}
	internal static class InteractionAnimationApiRestoreDiagnostics
	{
		internal sealed class CameraChainPoseSnapshot
		{
			private readonly Transform[] transforms;

			private readonly Vector3[] localPositions;

			private readonly string[] names;

			internal int Count => transforms.Length;

			internal string MissingTargets { get; }

			internal string Source { get; private set; } = "player_awake_prefix_authored_default";

			private CameraChainPoseSnapshot(Transform[] transforms, Vector3[] localPositions, string[] names, string missingTargets)
			{
				this.transforms = transforms;
				this.localPositions = localPositions;
				this.names = names;
				MissingTargets = missingTargets;
			}

			internal bool RefinePositions(string newSource)
			{
				//IL_0020: 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)
				bool flag = false;
				for (int i = 0; i < transforms.Length; i++)
				{
					Transform val = transforms[i];
					if (!((Object)(object)val == (Object)null))
					{
						localPositions[i] = val.localPosition;
						flag = true;
					}
				}
				if (flag)
				{
					Source = newSource;
				}
				return flag;
			}

			internal static CameraChainPoseSnapshot Capture(PlayerControllerB player)
			{
				List<Transform> list = new List<Transform>(4);
				List<Vector3> list2 = new List<Vector3>(4);
				List<string> list3 = new List<string>(4);
				List<string> list4 = new List<string>(4);
				CaptureTarget("cameraContainer", SafeGet(() => player.cameraContainerTransform), list, list2, list3, list4);
				CaptureTarget("gameplayCamera", SafeGet(() => (!((Object)(object)player.gameplayCamera != (Object)null)) ? null : ((Component)player.gameplayCamera).transform), list, list2, list3, list4);
				CaptureTarget("playerModelArmsMetarig", SafeGet(() => player.playerModelArmsMetarig), list, list2, list3, list4);
				CaptureTarget("localArmsTransform", SafeGet(() => player.localArmsTransform), list, list2, list3, list4);
				return new CameraChainPoseSnapshot(list.ToArray(), list2.ToArray(), list3.ToArray(), string.Join(",", list4.ToArray()));
			}

			private static Transform SafeGet(Func<Transform> getter)
			{
				try
				{
					return getter();
				}
				catch
				{
					return null;
				}
			}

			private static void CaptureTarget(string name, Transform target, List<Transform> capturedTransforms, List<Vector3> capturedPositions, List<string> capturedNames, List<string> missing)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)target == (Object)null)
				{
					missing.Add(name);
					return;
				}
				capturedTransforms.Add(target);
				capturedPositions.Add(target.localPosition);
				capturedNames.Add(name);
			}

			internal bool TryGetLocalPosition(string name, out Vector3 localPosition)
			{
				//IL_0039: 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_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				for (int i = 0; i < names.Length; i++)
				{
					if (string.Equals(names[i], name, StringComparison.Ordinal))
					{
						localPosition = localPositions[i];
						return true;
					}
				}
				localPosition = Vector3.zero;
				return false;
			}

			internal int RestorePositions()
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				for (int i = 0; i < transforms.Length; i++)
				{
					Transform val = transforms[i];
					if (!((Object)(object)val == (Object)null))
					{
						val.localPosition = localPositions[i];
						num++;
					}
				}
				return num;
			}

			internal string DescribePositions()
			{
				//IL_0027: Unknown result type (might be due to invalid IL or missing references)
				List<string> list = new List<string>(names.Length);
				for (int i = 0; i < names.Length; i++)
				{
					list.Add(names[i] + "Local=" + FormatVector(localPositions[i]));
				}
				return string.Join(" ", list.ToArray());
			}
		}

		private sealed class RestoreFrameSample
		{
			internal readonly int[] LayerStateHashes;

			internal readonly float[] LayerNormalizedTimes;

			internal bool Valid;

			internal int Frame;

			internal Vector3 GameplayCameraWorldPosition;

			internal Vector3 CameraContainerLocalPosition;

			internal Vector3 CameraContainerWorldPosition;

			internal Vector3 ArmsMetarigWorldPosition;

			internal string ControllerName;

			internal int ActualLayerCount;

			internal int CapturedLayerCount;

			internal RestoreFrameSample(int maxAnimatorLayers)
			{
				LayerStateHashes = new int[maxAnimatorLayers];
				LayerNormalizedTimes = new float[maxAnimatorLayers];
				ControllerName = "<null>";
			}
		}

		private sealed class RenderSeamFrameSample
		{
			internal bool Valid;

			internal PlayerControllerB Player;

			internal int Frame;

			internal float DeltaTime;

			internal float UnscaledDeltaTime;

			internal RenderPoseSample GameplayCamera;

			internal RenderPoseSample RightHand;

			internal RenderPoseSample LeftHand;

			internal RenderPoseSample ArmsMetarig;

			internal RenderPoseSample LocalArms;

			internal RenderPoseSample LocalVisor;

			internal RenderPoseSample LocalVisorTargetPoint;

			internal RenderVisibilitySample LocalVisorVisibility;

			internal bool VisorCameraPresent;

			internal bool VisorCameraEnabled;

			internal bool CameraParametersPresent;

			internal float CameraFieldOfView;

			internal float CameraNearClipPlane;

			internal RenderVisibilitySample HeldItem;

			internal void CopyFrom(RenderSeamFrameSample other)
			{
				if (other == null)
				{
					Reset();
					return;
				}
				Valid = other.Valid;
				Player = other.Player;
				Frame = other.Frame;
				DeltaTime = other.DeltaTime;
				UnscaledDeltaTime = other.UnscaledDeltaTime;
				GameplayCamera = other.GameplayCamera;
				RightHand = other.RightHand;
				LeftHand = other.LeftHand;
				ArmsMetarig = other.ArmsMetarig;
				LocalArms = other.LocalArms;
				LocalVisor = other.LocalVisor;
				LocalVisorTargetPoint = other.LocalVisorTargetPoint;
				LocalVisorVisibility = other.LocalVisorVisibility;
				VisorCameraPresent = other.VisorCameraPresent;
				VisorCameraEnabled = other.VisorCameraEnabled;
				CameraParametersPresent = other.CameraParametersPresent;
				CameraFieldOfView = other.CameraFieldOfView;
				CameraNearClipPlane = other.CameraNearClipPlane;
				HeldItem = other.HeldItem;
			}

			internal void Reset()
			{
				Valid = false;
				Player = null;
				Frame = 0;
				DeltaTime = 0f;
				UnscaledDeltaTime = 0f;
				GameplayCamera = default(RenderPoseSample);
				RightHand = default(RenderPoseSample);
				LeftHand = default(RenderPoseSample);
				ArmsMetarig = default(RenderPoseSample);
				LocalArms = default(RenderPoseSample);
				LocalVisor = default(RenderPoseSample);
				LocalVisorTargetPoint = default(RenderPoseSample);
				LocalVisorVisibility = default(RenderVisibilitySample);
				VisorCameraPresent = false;
				VisorCameraEnabled = false;
				CameraParametersPresent = false;
				CameraFieldOfView = 0f;
				CameraNearClipPlane = 0f;
				HeldItem = default(RenderVisibilitySample);
			}
		}

		private sealed class RenderSeamWindow
		{
			internal readonly string Phase;

			internal bool Active;

			internal int SeamFrame;

			internal int EndFrame;

			internal int LastLoggedFrame;

			internal GameObject AnimatedProp;

			internal RenderSeamWindow(string phase)
			{
				Phase = phase;
				Reset();
			}

			internal void Activate(int seamFrame, int endFrame, GameObject animatedProp)
			{
				Active = true;
				SeamFrame = seamFrame;
				EndFrame = endFrame;
				LastLoggedFrame = -1;
				AnimatedProp = animatedProp;
			}

			internal void Reset()
			{
				Active = false;
				SeamFrame = 0;
				EndFrame = 0;
				LastLoggedFrame = -1;
				AnimatedProp = null;
			}
		}

		private struct RenderPoseSample
		{
			internal bool Present;

			internal Vector3 WorldPosition;

			internal Vector3 WorldEulerAngles;
		}

		private struct RenderVisibilitySample
		{
			internal bool Present;

			internal string Name;

			internal bool ActiveInHierarchy;

			internal int RendererCount;

			internal int EnabledRendererCount;

			internal bool AnyRendererEnabled;

			internal bool ReadFailed;
		}

		internal sealed class ThirdPersonRigPoseSnapshot
		{
			private readonly ThirdPersonRigPoseBaseline[] baselines;

			internal int FullPoseCount { get; }

			internal int RotationOnlyCount { get; }

			internal int TotalCount => baselines.Length;

			internal bool IsComplete { get; }

			internal string MissingTargets { get; }

			internal bool PlausibleAtCapture { get; private set; }

			internal string Source { get; private set; } = "player_awake_prefix_authored_default";

			internal void SetCaptureMetadata(bool plausibleAtCapture, string source)
			{
				PlausibleAtCapture = plausibleAtCapture;
				Source = source;
			}

			private ThirdPersonRigPoseSnapshot(ThirdPersonRigPoseBaseline[] baselines, int fullPoseCount, int rotationOnlyCount, string[] missingTargets)
			{
				this.baselines = baselines ?? Array.Empty<ThirdPersonRigPoseBaseline>();
				FullPoseCount = fullPoseCount;
				RotationOnlyCount = rotationOnlyCount;
				IsComplete = missingTargets == null || missingTargets.Length == 0;
				MissingTargets = (IsComplete ? "<none>" : string.Join(",", missingTargets));
			}

			internal static ThirdPersonRigPoseSnapshot Capture(PlayerControllerB player)
			{
				Transform val = null;
				try
				{
					val = (((Object)(object)player != (Object)null && (Object)(object)player.playerBodyAnimator != (Object)null) ? ((Component)player.playerBodyAnimator).transform : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				Transform parent = FindChildRecursive(val, "spine.003");
				Transform parent2 = FindChildRecursive(val, "Rig 1");
				Transform val2 = FindDirectChild(parent2, "LeftLeg");
				Transform val3 = FindDirectChild(parent2, "RightLeg");
				List<ThirdPersonRigPoseBaseline> list = new List<ThirdPersonRigPoseBaseline>(12);
				HashSet<Transform> capturedTransforms = new HashSet<Transform>();
				List<string> list2 = new List<string>(10);
				AddFullPose(FindDirectChild(parent, "LeftArm_target"), "spine.003/LeftArm_target", list, capturedTransforms, list2);
				AddFullPose(FindDirectChild(parent, "RightArm_target"), "spine.003/RightArm_target", list, capturedTransforms, list2);
				AddControlGroup(val2, "Rig 1/LeftLeg", new string[2] { "LeftLeg_hint", "LeftLeg_target" }, list, capturedTransforms, list2);
				AddControlGroup(val3, "Rig 1/RightLeg", new string[2] { "RightLeg_hint", "RightLeg_target" }, list, capturedTransforms, list2);
				AddRotationOnly(FindChildRecursive(val, "shin.L"), "spine/thigh.L/shin.L", list, capturedTransforms, list2);
				AddRotationOnly(FindChildRecursive(val, "shin.R"), "spine/thigh.R/shin.R", list, capturedTransforms, list2);
				int num = 0;
				int num2 = 0;
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i].RotationOnly)
					{
						num2++;
					}
					else
					{
						num++;
					}
				}
				return new ThirdPersonRigPoseSnapshot(list.ToArray(), num, num2, list2.ToArray());
			}

			private static void AddControlGroup(Transform group, string groupPath, string[] requiredChildren, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)group == (Object)null)
				{
					missing.Add(groupPath);
					for (int i = 0; i < requiredChildren.Length; i++)
					{
						missing.Add(groupPath + "/" + requiredChildren[i]);
					}
					return;
				}
				Transform[] componentsInChildren = ((Component)group).GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					string relativePath = GetRelativePath(group, val);
					string path = ((group == val) ? groupPath : (groupPath + relativePath.Substring(((Object)group).name.Length)));
					AddFullPose(val, path, captured, capturedTransforms, null);
				}
				foreach (string text in requiredChildren)
				{
					if ((Object)(object)FindDirectChild(group, text) == (Object)null)
					{
						missing.Add(groupPath + "/" + text);
					}
				}
			}

			private static void AddFullPose(Transform transform, string path, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)transform == (Object)null)
				{
					missing?.Add(path);
				}
				else if (capturedTransforms.Add(transform))
				{
					captured.Add(new ThirdPersonRigPoseBaseline(transform, path, rotationOnly: false));
				}
			}

			private static void AddRotationOnly(Transform transform, string path, ICollection<ThirdPersonRigPoseBaseline> captured, ISet<Transform> capturedTransforms, ICollection<string> missing)
			{
				if ((Object)(object)transform == (Object)null)
				{
					missing.Add(path);
				}
				else if (capturedTransforms.Add(transform))
				{
					captured.Add(new ThirdPersonRigPoseBaseline(transform, path, rotationOnly: true));
				}
			}

			internal ThirdPersonRigPlausibility EvaluateVanillaRestPlausibility()
			{
				//IL_004f: 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_0085: 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_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				int num2 = 0;
				int num3 = 0;
				float num4 = 0f;
				float num5 = 0f;
				float num6 = 0f;
				bool flag = false;
				for (int i = 0; i < baselines.Length; i++)
				{
					ThirdPersonRigPoseBaseline thirdPersonRigPoseBaseline = baselines[i];
					if (!thirdPersonRigPoseBaseline.HasExpectedVanillaRest)
					{
						continue;
					}
					if (!thirdPersonRigPoseBaseline.Finite)
					{
						flag = true;
						continue;
					}
					float num7 = Quaternion.Angle(thirdPersonRigPoseBaseline.ExpectedLocalRotation, thirdPersonRigPoseBaseline.LocalRotation);
					num5 = Mathf.Max(num5, num7);
					if (num7 > 8f)
					{
						num2++;
					}
					if (!thirdPersonRigPoseBaseline.RotationOnly)
					{
						float num8 = Vector3.Distance(thirdPersonRigPoseBaseline.ExpectedLocalPosition, thirdPersonRigPoseBaseline.LocalPosition);
						float num9 = Vector3.Distance(thirdPersonRigPoseBaseline.ExpectedLocalScale, thirdPersonRigPoseBaseline.LocalScale);
						num4 = Mathf.Max(num4, num8);
						num6 = Mathf.Max(num6, num9);
						if (num8 > 0.05f)
						{
							num++;
						}
						if (num9 > 0.01f)
						{
							num3++;
						}
					}
				}
				bool flag2 = IsComplete && !flag && num == 0 && num2 == 0 && num3 == 0;
				string reason = ((!IsComplete) ? "required_transforms_missing" : (flag ? "non_finite_local_pose" : (flag2 ? "within_vanilla_rest_thresholds" : "outside_vanilla_rest_thresholds")));
				return new ThirdPersonRigPlausibility(flag2, reason, num, num2, num3, num4, num5, num6);
			}

			internal void RestoreExcept(ISet<Transform> excludedTransforms, ISet<Transform> restoredTransforms, out int fullPoseRestored, out int rotationOnlyRestored)
			{
				fullPoseRestored = 0;
				rotationOnlyRestored = 0;
				for (int i = 0; i < baselines.Length; i++)
				{
					ThirdPersonRigPoseBaseline thirdPersonRigPoseBaseline = baselines[i];
					Transform transform = thirdPersonRigPoseBaseline.Transform;
					if (!((Object)(object)transform == (Object)null) && (excludedTransforms == null || !excludedTransforms.Contains(transform)) && thirdPersonRigPoseBaseline.Restore())
					{
						restoredTransforms?.Add(transform);
						if (thirdPersonRigPoseBaseline.RotationOnly)
						{
							rotationOnlyRestored++;
						}
						else
						{
							fullPoseRestored++;
						}
					}
				}
			}
		}

		private sealed class ThirdPersonRigPoseBaseline
		{
			internal Transform Transform { get; }

			internal string Path { get; }

			internal bool RotationOnly { get; }

			internal Vector3 LocalPosition { get; }

			internal Quaternion LocalRotation { get; }

			internal Vector3 LocalScale { get; }

			internal bool HasExpectedVanillaRest { get; }

			internal Vector3 ExpectedLocalPosition { get; }

			internal Quaternion ExpectedLocalRotation { get; }

			internal Vector3 ExpectedLocalScale { get; }

			internal bool Finite
			{
				get
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing ref