Decompiled source of AvatarAnimator v1.0.0

Mods/AvatarAnimator.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using AvatarAnimator;
using AvatarAnimator.Deserialize;
using AvatarAnimator.FusionLab;
using BoneLib;
using BoneLib.BoneMenu;
using FieldInjector;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Network.Serialization;
using LabFusion.Player;
using LabFusion.SDK.Modules;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("AvatarAnimator")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AvatarAnimator")]
[assembly: AssemblyCopyright("Created by Daedalus")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: MelonColor(255, 0, 128, 0)]
[assembly: MelonInfo(typeof(Core), "AvatarAnimator", "1.0.0", "Daedalus", "")]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyVersion("1.0.0.0")]
public static class AssemblyVar
{
	public const int ColorR = 0;

	public const int ColorG = 128;

	public const int ColorB = 0;
}
namespace AvatarAnimator
{
	public static class Config
	{
		private static readonly DelayTimeGate delay = new DelayTimeGate(20.0);

		private static bool SaveLaterActif = false;

		private static MelonPreferences_Category cat;

		private static MelonPreferences_Entry<bool> debugLog;

		private static MelonPreferences_Entry<int> scanMirrorsInterval;

		private static MelonPreferences_Entry<int> playerAnimatorUpdateInterval;

		public static int ScanMirrorsInterval => scanMirrorsInterval.Value;

		public static ValueRange<int> ScanMirrorsIntervalRange => (ValueRange<int>)(object)((MelonPreferences_Entry)scanMirrorsInterval).Validator;

		public static int PlayerAnimatorUpdateInterval => playerAnimatorUpdateInterval.Value;

		public static ValueRange<int> PlayerAnimatorUpdateIntervalRange => (ValueRange<int>)(object)((MelonPreferences_Entry)playerAnimatorUpdateInterval).Validator;

		public static event Action<bool> OnSaveStateChange;

		public static void Initialize()
		{
			cat = MelonPreferences.CreateCategory("AvatarAnimator", "");
			debugLog = cat.CreateEntry<bool>("Debug_Logs", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			Logger.DebugLogs = debugLog.Value;
			scanMirrorsInterval = cat.CreateEntry<int>("Scan_Mirrors_Interval", 20, "Delay in frame between each Mirror scan", (string)null, false, false, (ValueValidator)(object)new ValueRange<int>(1, 60), (string)null);
			playerAnimatorUpdateInterval = cat.CreateEntry<int>("Player_Animator_Update_Interval", 2, "Delay in frame between each Player animator update", (string)null, false, false, (ValueValidator)(object)new ValueRange<int>(1, 4), (string)null);
			SavePreferences();
		}

		public static void SwitchDebugLog(bool on)
		{
			if (on != Logger.DebugLogs)
			{
				bool debugLogs = (debugLog.Value = on);
				Logger.DebugLogs = debugLogs;
				SavePreferencesLater();
			}
		}

		public static void ChangeScanMirrorsInterval(int interval)
		{
			if (interval != scanMirrorsInterval.Value)
			{
				UpdateTimeGate updateScanner = CorePrivate.UpdateScanner;
				int interval2 = (scanMirrorsInterval.Value = interval);
				updateScanner.Interval = interval2;
				SavePreferencesLater();
			}
		}

		public static void ChangePlayerAnimatorUpdateInterval(int interval)
		{
			if (interval != playerAnimatorUpdateInterval.Value)
			{
				UpdateTimeGate updateAnim = CorePrivate.UpdateAnim;
				int interval2 = (playerAnimatorUpdateInterval.Value = interval);
				updateAnim.Interval = interval2;
				SavePreferencesLater();
			}
		}

		public static void SavePreferences()
		{
			MelonPreferences.Save();
			if (SaveLaterActif)
			{
				SaveLaterActif = false;
				Config.OnSaveStateChange?.Invoke(SaveLaterActif);
				UpdateSystem.Remove(DelayUpdate);
			}
		}

		public static void SavePreferencesLater()
		{
			delay.Reset();
			if (!SaveLaterActif)
			{
				SaveLaterActif = true;
				Config.OnSaveStateChange?.Invoke(SaveLaterActif);
				UpdateSystem.CallLater(DelayUpdate);
			}
		}

		private static void DelayUpdate()
		{
			if (delay.Now())
			{
				SavePreferences();
			}
		}
	}
	public static class Const
	{
		public const string PolyBlankBarcode = "c3534c5a-94b2-40a4-912a-24a8506f6c79";

		public const string PolyBlankAvatar = "PolyBlank";

		public const string True = "true";
	}
	public static class PlayerMetadataChangedKeys
	{
		public const string Loading = "Loading";

		public const string LevelBarcode = "LevelBarcode";

		public const string AvatarModID = "AvatarModID";

		public const string Description = "Description";

		public const string Nickname = "Nickname";

		public const string AvatarTitle = "AvatarTitle";
	}
	public static class BuildInfo
	{
		public const string Name = "AvatarAnimator";

		public const string Author = "Daedalus";

		public const string Company = "";

		public const string Version = "1.0.0";

		public const string DownloadLink = "";

		public const uint ConsoleColorRGB = 32768u;
	}
	public class Core : MelonMod
	{
		private static bool enabled;

		public static bool IsLevelLoading => !enabled;

		public event Action<PlayerStateChange> OnAvatarStateChanged;

		public event Action<EntityData> OnPlayerAvatarChange;

		public event Action<EntityData> OnPlayerAvatarSame;

		public void PlayState(int layerIndex, string state)
		{
			PlayerAnimator.PlayState(layerIndex, state);
		}

		public override void OnInitializeMelon()
		{
			Config.Initialize();
			CorePrivate.Initalize();
			Logger.Initialize(((MelonBase)this).LoggerInstance);
			MenuUi.Initialize();
			PlayerAnimator.Initialize();
			FieldInjectorInteg.InjectFields();
			Hooking.OnLevelUnloaded += delegate
			{
				enabled = false;
				MirrorScanner.Clear();
			};
			Hooking.OnLevelLoading += delegate
			{
				enabled = false;
			};
			Hooking.OnLevelLoaded += delegate
			{
				enabled = true;
				CorePrivate.UpdateScanner.Reset();
			};
			FusionLabLoader.Initialise();
			PlayerAnimator.OnAvatarStateChanged += this.OnAvatarStateChanged;
			PlayerScanner.OnAvatarChange += this.OnPlayerAvatarChange;
			PlayerScanner.OnAvatarSame += this.OnPlayerAvatarSame;
		}

		public override void OnUpdate()
		{
			if (enabled)
			{
				LocalInput.Update();
				UpdateSystem.Update();
				if (CorePrivate.UpdateScanner.Now())
				{
					MirrorScanner.Scan();
				}
				if (CorePrivate.UpdateAnim.Now())
				{
					PlayerAnimator.Update();
				}
			}
		}
	}
	public static class CorePrivate
	{
		private static UpdateTimeGate updateScanner;

		private static UpdateTimeGate updateAnim;

		private static bool switchAvatarHooked;

		public static UpdateTimeGate UpdateScanner => updateScanner;

		public static UpdateTimeGate UpdateAnim => updateAnim;

		public static void Initalize()
		{
			updateScanner = new UpdateTimeGate(Config.ScanMirrorsInterval);
			updateAnim = new UpdateTimeGate(Config.PlayerAnimatorUpdateInterval);
		}

		public static void UpdatePlayerAvatar()
		{
			UpdateSystem.CallLaterOnce("UpdateAvatarChangeLater", delegate
			{
				PlayerScanner.GetAvatarAnimator();
			});
		}

		private static void OnSwitchAvatarPostfix(Avatar _)
		{
			UpdatePlayerAvatar();
		}

		public static void SimplePlayerMonitoring()
		{
			if (!switchAvatarHooked)
			{
				Logger.Dbg?.Info("Simple PlayerMonitoring");
				Hooking.OnSwitchAvatarPostfix += OnSwitchAvatarPostfix;
				switchAvatarHooked = true;
			}
		}

		public static void MultiPlayerMonitoring()
		{
			if (switchAvatarHooked)
			{
				Logger.Dbg?.Info("Multiplayer PlayerMonitoring");
				Hooking.OnSwitchAvatarPostfix -= OnSwitchAvatarPostfix;
				switchAvatarHooked = false;
			}
		}
	}
	public static class FieldInjectorInteg
	{
		public static void InjectFields()
		{
			Logger.Msg("AvatarAnimator components injection start!");
			SerialisationHandler.Inject<AvatarAnimatorDataContainer>(0);
			Logger.Msg("AvatarAnimator components injected successfully!");
		}
	}
	public static class FusionLabLoader
	{
		public static void Initialise()
		{
			if (MelonBase.FindMelon("LabFusion", "Lakatrazz") != null)
			{
				Logger.Msg("LabFusion detected - registering multiplayer module...");
				try
				{
					AvatarAnimatorFusionModuleLoader.LoadModule();
					Logger.Msg("Fusion module registered successfully!");
					return;
				}
				catch (Exception ex)
				{
					Logger.Err("Error registering Fusion module: " + ex.Message);
				}
			}
			else
			{
				Logger.Msg("LabFusion not detected - running in singleplayer mode");
			}
			CorePrivate.SimplePlayerMonitoring();
		}
	}
	public static class Logger
	{
		public class DebugLogger
		{
			public void Log(ConsoleColor color, string msg)
			{
				m_Logger.Msg(color, msg);
			}

			public void Log(string msg)
			{
				m_Logger.Msg(msg);
			}

			public void Debug(string msg)
			{
				Log(ConsoleColor.Green, "[Dbg-Debug] " + msg);
			}

			public void Data(string msg)
			{
				Log(ConsoleColor.Magenta, "[Dbg-Data] " + msg);
			}

			public void Info(string msg)
			{
				Log(ConsoleColor.Cyan, "[Dbg-Info] " + msg);
			}

			public void Highlight(string msg)
			{
				Log(ConsoleColor.DarkRed, "[Dbg-High] " + msg);
			}

			public void StackTrace()
			{
				Log(ConsoleColor.DarkRed, "[StackTrace] " + new StackTrace().ToString());
			}

			public void Warn(string msg)
			{
				Log(ConsoleColor.Yellow, "[Dbg-W] " + msg);
			}

			public void Err(string msg)
			{
				Log(ConsoleColor.Red, "[Dbg-E] " + msg);
			}
		}

		private static Instance m_Logger;

		private static DebugLogger m_Dbg;

		private static bool m_DebugLogs;

		public static bool DebugLogs
		{
			get
			{
				return m_DebugLogs;
			}
			set
			{
				m_DebugLogs = value;
				m_Dbg = (value ? new DebugLogger() : null);
			}
		}

		public static DebugLogger Dbg => m_Dbg;

		public static void Initialize(Instance logger)
		{
			m_Logger = logger;
		}

		public static void Msg(string msg)
		{
			m_Logger.Msg(msg);
		}

		public static void Warn(string msg)
		{
			m_Logger.Warning("[W] " + msg);
		}

		public static void Err(string msg)
		{
			m_Logger.Error("[E] " + msg);
		}
	}
	public static class MenuUi
	{
		private static Page m_modPage;

		private static Page m_AvatarStatePage;

		private static Page m_ConfigPage;

		private static FunctionElement m_ConfigSaveButton;

		private static readonly List<FunctionElement> ListAction = new List<FunctionElement>();

		public static void Initialize()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			m_modPage = Page.Root.CreatePage("AvatarAnimator", Color.cyan, 0, true);
			m_AvatarStatePage = m_modPage.CreatePage("Play Avatar state", Color.green, 0, true);
			PlayerScanner.OnAvatarChange += OnAvatarChanged;
			InitializeConfigPage();
		}

		private static void InitializeConfigPage()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			m_ConfigPage = m_modPage.CreatePage("Configs", Color.white, 0, true);
			m_ConfigSaveButton = m_ConfigPage.CreateFunction("Save", Color.white, (Action)delegate
			{
				Config.SavePreferences();
			});
			SaveButtonState(ModificationPending: false);
			((Element)m_ConfigSaveButton).ElementTooltip = "Save configuration changes \n Black: No change, Cyan: Change pending (auto-save after 20 sec)";
			Config.OnSaveStateChange += SaveButtonState;
			BoolElement val = m_ConfigPage.CreateBool("Debug Logs", Color.white, Logger.DebugLogs, (Action<bool>)delegate(bool on)
			{
				Config.SwitchDebugLog(on);
			});
			((Element)val).ElementTooltip = "Enable Debug logs";
			ValueRange<int> scanMirrorsIntervalRange = Config.ScanMirrorsIntervalRange;
			IntElement val2 = m_ConfigPage.CreateInt("Scan Mirror Interval", Color.white, Config.ScanMirrorsInterval, 1, scanMirrorsIntervalRange.MinValue, scanMirrorsIntervalRange.MaxValue, (Action<int>)delegate(int interval)
			{
				Config.ChangeScanMirrorsInterval(interval);
			});
			((Element)val2).ElementTooltip = $"Number of update before a scan for Mirror enities [{scanMirrorsIntervalRange.MinValue}; {scanMirrorsIntervalRange.MaxValue}] default: 20 \n This may affect performance if set too low.";
			ValueRange<int> playerAnimatorUpdateIntervalRange = Config.PlayerAnimatorUpdateIntervalRange;
			IntElement val3 = m_ConfigPage.CreateInt("Player animator update Interval", Color.white, Config.PlayerAnimatorUpdateInterval, 1, playerAnimatorUpdateIntervalRange.MinValue, playerAnimatorUpdateIntervalRange.MaxValue, (Action<int>)delegate(int interval)
			{
				Config.ChangePlayerAnimatorUpdateInterval(interval);
			});
			((Element)val3).ElementTooltip = $"Number of update before a an update for the player Animator [{playerAnimatorUpdateIntervalRange.MinValue}; {playerAnimatorUpdateIntervalRange.MaxValue}] default: 2";
		}

		public static void SaveButtonState(bool ModificationPending)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (m_ConfigSaveButton != null)
			{
				((Element)m_ConfigSaveButton).ElementColor = (ModificationPending ? Color.cyan : Color.black);
			}
		}

		public static void OnAvatarChanged(EntityData player)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			int count = ListAction.Count;
			foreach (FunctionElement item in ListAction)
			{
				m_AvatarStatePage.Remove((Element)(object)item);
			}
			ListAction.Clear();
			if (player?.Container?.m_Data == null)
			{
				Logger.Dbg?.Info("MenuUi: No Avatar Animator data");
				AddButton("Avatar doesn't have Animation", Color.red, delegate
				{
				});
				return;
			}
			Logger.Dbg?.Info("MenuUi: Avatar Animator data found");
			foreach (LayerData item2 in player.Data.ListLayer)
			{
				foreach (KeyValuePair<string, StateNode> state in item2.States)
				{
					int layer = item2.LayerIndex;
					string stateName = state.Key;
					AddButton($"{layer} - {stateName}", Color.white, delegate
					{
						PlayerAnimator.PlayState(layer, stateName);
					});
				}
			}
			Logger.Dbg?.Info($"Update MenuUi AvatarStatePage, removed {count}, Added {ListAction.Count} buttons");
		}

		private static void AddButton(string text, Color textColor, Action func)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			ListAction.Add(m_AvatarStatePage.CreateFunction(text, textColor, func));
		}
	}
	[Serializable]
	public class PlayerStateChange
	{
		[JsonProperty("Layer")]
		public int m_Layer;

		[JsonProperty("State")]
		public string m_State;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public float? m_nTime = null;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public float? m_Duration = null;

		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public float? m_Speed = null;

		[JsonProperty("Now")]
		public DateTime now;

		public PlayerStateChange()
		{
		}

		public PlayerStateChange(int layer, string state, float len, float speed, float? nTime = null)
		{
			m_Layer = layer;
			m_State = state;
			m_Duration = len;
			m_Speed = speed;
			now = DateTime.Now;
			m_nTime = nTime;
		}
	}
	public static class PlayerAnimator
	{
		public class AnimatorLayer
		{
			public readonly int m_LayerIndex;

			public StateNode m_CurrentState = null;

			public string m_CurrentStateName;

			public DateTime? m_Transition = null;

			public DateTime? m_ConditionDelayTimer = null;

			public DateTime? m_ConditionDelayWaitEndClip = null;

			public DateTime? m_startAt;

			public AnimatorLayer(int layerIndex)
			{
				m_LayerIndex = layerIndex;
			}
		}

		private static readonly List<EntityData> m_mirrorAnimators = new List<EntityData>();

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

		private static readonly List<AnimatorLayer> m_Layers = new List<AnimatorLayer>();

		private static EntityData m_player = null;

		private static string m_oldAvatar = "";

		private static readonly Dictionary<string, int> m_StoreValues = new Dictionary<string, int>();

		public static bool IsValid => (Object)null != (Object)(object)m_player?.Container && m_player.IsValid;

		public static byte Id => m_player.Id;

		public static event Action<PlayerStateChange> OnAvatarStateChanged;

		public static void Initialize()
		{
			PlayerScanner.OnAvatarChange += AvatarChange;
			PlayerScanner.OnAvatarSame += SameAvatar;
			MirrorScanner.OnNew += AddMirror;
			MirrorScanner.OnRemoved += RemoveMirror;
			MirrorScanner.OnClear += ClearMirrors;
			Logger.Msg("Avatar animator data current version 1.0");
		}

		private static void AvatarChange(EntityData player)
		{
			Logger.Dbg?.Info("OnAvatarChange");
			PlayerInput.Clear();
			string text = ((Object)player.Barcode).ToString();
			if ("c3534c5a-94b2-40a4-912a-24a8506f6c79" != text)
			{
				m_StoreValues.Clear();
				m_Layers.Clear();
				m_LayerIndexToIndex.Clear();
				m_oldAvatar = text;
			}
			else if (text == m_oldAvatar)
			{
				SameAvatar(player);
				return;
			}
			m_player = player;
			if (!m_player.HasAvatarAnimatorData)
			{
				Logger.Dbg?.Info("PlayerAvatarChange: Current Animator doesn't have data");
				return;
			}
			foreach (KeyValuePair<string, TransitionConditionData> transitionsDatum in m_player.Data.TransitionsData)
			{
				switch (transitionsDatum.Value.Type)
				{
				case ConditionType.Input:
					PlayerInput.Initialise(transitionsDatum.Value);
					break;
				case ConditionType.Random:
				case ConditionType.Cyclic:
					m_StoreValues.Add(transitionsDatum.Key, -1);
					break;
				}
			}
			foreach (EntityData mirrorAnimator in m_mirrorAnimators)
			{
				mirrorAnimator.UpdateAvatar();
			}
			if (!IsValid)
			{
				return;
			}
			int num = 0;
			foreach (LayerData item in m_player.Data.ListLayer)
			{
				m_Layers.Add(new AnimatorLayer(item.LayerIndex));
				m_LayerIndexToIndex.Add(item.LayerIndex, num);
				PlayState(item.LayerIndex, item.StartState, null, updateValues: true, playState: false);
				num++;
			}
		}

		private static void SameAvatar(EntityData player)
		{
			Logger.Dbg?.Info("OnAvatarSame");
			m_player = player;
			if (!m_player.HasAvatarAnimatorData)
			{
				Logger.Dbg?.Info("PlayerAvatarSame: Current Animator doesn't have data");
			}
			else
			{
				if (!IsValid)
				{
					return;
				}
				foreach (KeyValuePair<string, TransitionConditionData> transitionsDatum in m_player.Data.TransitionsData)
				{
					ConditionType type = transitionsDatum.Value.Type;
					ConditionType conditionType = type;
					if (conditionType == ConditionType.Random || conditionType == ConditionType.Cyclic)
					{
						m_player.Animator.SetInteger(transitionsDatum.Key, m_StoreValues[transitionsDatum.Key]);
					}
				}
				foreach (AnimatorLayer layer in m_Layers)
				{
					PlayState(layer.m_LayerIndex, layer.m_CurrentStateName, layer.m_startAt, updateValues: false);
				}
			}
		}

		private static void AddMirror(EntityData data)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			Logger.Dbg?.Info($"Data:({((Object)data.Barcode).ToString()} PlayerID:'{data.Id}') Player:({((Object)m_player.Barcode).ToString()} PlayerID:'{m_player.Id}')");
			if (data.Barcode != m_player.Barcode || data.Id != m_player.Id)
			{
				return;
			}
			Logger.Dbg?.Info("Add Mirror to Player");
			m_mirrorAnimators.Add(data);
			if (!IsValid)
			{
				return;
			}
			foreach (AnimatorLayer layer in m_Layers)
			{
				AnimatorStateInfo currentAnimatorStateInfo = m_player.Animator.GetCurrentAnimatorStateInfo(layer.m_LayerIndex);
				data.Animator.Play(layer.m_CurrentStateName, layer.m_LayerIndex, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime);
			}
		}

		private static void RemoveMirror(EntityData data)
		{
			m_mirrorAnimators.Remove(data);
		}

		private static void ClearMirrors()
		{
			m_mirrorAnimators.Clear();
		}

		public static void PlayState(int layer, string state, DateTime? time = null, bool updateValues = true, bool playState = true)
		{
			if (!IsValid || !m_LayerIndexToIndex.ContainsKey(layer))
			{
				return;
			}
			DateTime playAt = time ?? DateTime.Now;
			int index = m_LayerIndexToIndex[layer];
			AnimatorLayer animatorLayer = m_Layers[index];
			animatorLayer.m_startAt = time ?? DateTime.Now;
			animatorLayer.m_CurrentStateName = state;
			animatorLayer.m_CurrentState = m_player.Data.ListLayer[index].States[state];
			Logger.Msg("Player: " + ((Object)m_player.Barcode).ToString() + " Current state change to '" + state + "'");
			Logger.Dbg?.Data(JsonConvert.SerializeObject((object)animatorLayer.m_CurrentState, (Formatting)0));
			StateNode currentState = animatorLayer.m_CurrentState;
			float num = Utils.ComputNTime(DateTime.Now, playAt, 0f, currentState.ClipDuration, currentState.Speed);
			if (playState)
			{
				m_player.Animator.Play(state, layer, num);
			}
			foreach (EntityData mirrorAnimator in m_mirrorAnimators)
			{
				mirrorAnimator.Animator.Play(state, layer, num);
			}
			PlayerAnimator.OnAvatarStateChanged?.Invoke(new PlayerStateChange(layer, state, animatorLayer.m_CurrentState.ClipDuration, animatorLayer.m_CurrentState.Speed, num));
			if (!updateValues)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (Transition transition in animatorLayer.m_CurrentState.Transitions)
			{
				foreach (TransitionCondition condition in transition.Conditions)
				{
					if (!hashSet.Contains(condition.Name))
					{
						switch (condition.Type)
						{
						case ConditionType.Random:
						{
							TransitionConditionData transitionConditionData2 = m_player.Data.TransitionsData[condition.Name];
							int num3 = Utils.RandomInt(transitionConditionData2.Min, transitionConditionData2.Max);
							m_StoreValues[condition.Name] = num3;
							m_player.Animator.SetInteger(condition.Name, num3);
							break;
						}
						case ConditionType.Cyclic:
						{
							TransitionConditionData transitionConditionData = m_player.Data.TransitionsData[condition.Name];
							int num2 = (m_player.Animator.GetInteger(condition.Name) + 1) % transitionConditionData.Max;
							m_StoreValues[condition.Name] = num2;
							m_player.Animator.SetInteger(condition.Name, num2);
							break;
						}
						}
						hashSet.Add(condition.Name);
					}
				}
			}
		}

		public static void Update()
		{
			if (!IsValid)
			{
				return;
			}
			PlayerInput.Next();
			foreach (AnimatorLayer layer in m_Layers)
			{
				if (layer.m_Transition.HasValue)
				{
					DateTime now = DateTime.Now;
					DateTime? transition = layer.m_Transition;
					if (now > transition)
					{
						layer.m_Transition = null;
						layer.m_ConditionDelayTimer = null;
						layer.m_ConditionDelayWaitEndClip = null;
					}
					break;
				}
				foreach (Transition transition2 in layer.m_CurrentState.Transitions)
				{
					bool flag = true;
					foreach (TransitionCondition condition in transition2.Conditions)
					{
						flag = IsConditionValid(layer, condition);
						if (!flag)
						{
							break;
						}
					}
					if (flag || transition2.HasExitTime)
					{
						layer.m_Transition = Utils.DateTimeNowPlusSecs(transition2.HasExitTime ? transition2.ExitTime : transition2.Duration);
						PlayState(layer.m_LayerIndex, transition2.NextState, null, updateValues: true, playState: false);
						break;
					}
				}
			}
		}

		private static bool IsConditionValid(AnimatorLayer layer, TransitionCondition cond)
		{
			if (cond == null)
			{
				return true;
			}
			switch (cond.Type)
			{
			case ConditionType.Input:
			{
				TransitionConditionData transitionConditionData = m_player.Data.TransitionsData[cond.Name];
				foreach (ConditionInput input in transitionConditionData.Inputs)
				{
					if (PlayerInput.IsTriggered(input))
					{
						m_player.Animator.SetTrigger(cond.Name);
						return true;
					}
				}
				return false;
			}
			case ConditionType.Health:
			{
				Health health = Player.RigManager.health;
				float num = health.curr_Health / health.max_Health;
				m_player.Animator.SetFloat(cond.Name, num);
				return Utils.Is(cond.Mode, num, cond.Threshold);
			}
			case ConditionType.Random:
				return Utils.Is(cond.Mode, m_player.Animator.GetInteger(cond.Name), (int)cond.Threshold);
			case ConditionType.Timer:
			{
				if (!layer.m_ConditionDelayTimer.HasValue)
				{
					layer.m_ConditionDelayTimer = DateTime.Now.AddSeconds(cond.Threshold);
				}
				DateTime now = DateTime.Now;
				DateTime? conditionDelayWaitEndClip = layer.m_ConditionDelayTimer;
				if (now > conditionDelayWaitEndClip)
				{
					m_player.Animator.SetTrigger(cond.Name);
					return true;
				}
				return false;
			}
			case ConditionType.WaitEndClip:
			{
				if (!layer.m_ConditionDelayWaitEndClip.HasValue)
				{
					layer.m_ConditionDelayWaitEndClip = DateTime.Now.AddSeconds(layer.m_CurrentState.ClipDuration / Math.Abs(layer.m_CurrentState.Speed));
				}
				DateTime now = DateTime.Now;
				DateTime? conditionDelayWaitEndClip = layer.m_ConditionDelayWaitEndClip;
				if (now > conditionDelayWaitEndClip)
				{
					m_player.Animator.SetTrigger(cond.Name);
					return true;
				}
				return false;
			}
			case ConditionType.Cyclic:
				return Utils.Is(cond.Mode, m_player.Animator.GetInteger(cond.Name), (int)cond.Threshold);
			default:
				return true;
			}
		}

		public static List<PlayerStateChange> GetPlayerStates()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			List<PlayerStateChange> list = new List<PlayerStateChange>();
			if (!IsValid)
			{
				return list;
			}
			foreach (AnimatorLayer layer in m_Layers)
			{
				AnimatorStateInfo currentAnimatorStateInfo = m_player.Animator.GetCurrentAnimatorStateInfo(layer.m_LayerIndex);
				list.Add(new PlayerStateChange(layer.m_LayerIndex, layer.m_CurrentStateName, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length, currentAnimatorStateInfo.m_Speed, currentAnimatorStateInfo.m_NormalizedTime));
			}
			return list;
		}
	}
	public static class LocalInput
	{
		private static readonly HashSet<KeyCode> m_KeyboardInputs = new HashSet<KeyCode>();

		private static readonly HashSet<ControllerInputs> m_ControllerInputs = new HashSet<ControllerInputs>();

		public static void Update()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			foreach (KeyCode keyboardInput in m_KeyboardInputs)
			{
				if (!Input.GetKey(keyboardInput))
				{
					m_KeyboardInputs.Remove(keyboardInput);
				}
			}
			foreach (ControllerInputs controllerInput in m_ControllerInputs)
			{
				if (!GetControllerTrigger(controllerInput))
				{
					m_ControllerInputs.Remove(controllerInput);
				}
			}
		}

		public static bool GetKeyDown(KeyCode code)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKey(code) && !m_KeyboardInputs.Contains(code))
			{
				m_KeyboardInputs.Add(code);
				return true;
			}
			return false;
		}

		public static bool GetControllerTriggerDown(ControllerInputs input)
		{
			if (GetControllerTrigger(input) && !m_ControllerInputs.Contains(input))
			{
				m_ControllerInputs.Add(input);
				return true;
			}
			return false;
		}

		public static bool GetControllerTrigger(ControllerInputs input)
		{
			if (1 == 0)
			{
			}
			bool result = input switch
			{
				ControllerInputs.A => Player.RightController.GetAButton(), 
				ControllerInputs.B => Player.RightController.GetBButton(), 
				ControllerInputs.X => Player.LeftController.GetAButton(), 
				ControllerInputs.Y => Player.LeftController.GetBButton(), 
				ControllerInputs.LeftGrip => (double)Player.LeftController.GetGripForce() > 0.8, 
				ControllerInputs.RightGrip => (double)Player.RightController.GetGripForce() > 0.8, 
				ControllerInputs.LeftTrigger => Player.LeftController.GetGrabbedState(), 
				ControllerInputs.RightTrigger => Player.RightController.GetGrabbedState(), 
				ControllerInputs.Menu => Player.LeftController.GetMenuButton(), 
				ControllerInputs.SecondaryMenu => Player.RightController.GetSecondaryMenuButtonDown(), 
				ControllerInputs.LeftThumbStick => Player.LeftController.GetThumbStick(), 
				ControllerInputs.RightThumbStick => Player.RightController.GetThumbStick(), 
				ControllerInputs.LeftTouchPad => Player.LeftController.GetTouchPad(), 
				ControllerInputs.RightTouchPad => Player.RightController.GetTouchPad(), 
				_ => throw new Exception($"Invalid Controller input name '{input}'"), 
			};
			if (1 == 0)
			{
			}
			return result;
		}
	}
	public static class PlayerInput
	{
		private static long m_frame = 0L;

		private static readonly Dictionary<string, long> m_inputPressed = new Dictionary<string, long>();

		public static void Clear()
		{
			m_frame = 0L;
			m_inputPressed.Clear();
		}

		public static void Initialise(TransitionConditionData data)
		{
			foreach (ConditionInput input in data.Inputs)
			{
				m_inputPressed.Add(input.InputName, -1L);
			}
		}

		public static void Next()
		{
			m_frame++;
		}

		public static bool IsTriggered(ConditionInput trans)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Invalid comparison between Unknown and I4
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (trans.Type == InputType.Unset)
			{
				return false;
			}
			switch (trans.Type)
			{
			case InputType.Keyboard:
				if (LocalInput.GetKeyDown(trans.KeyCode) || m_frame == m_inputPressed[trans.InputName])
				{
					m_inputPressed[trans.InputName] = m_frame;
					if ((int)trans.KeyCode2 == 0)
					{
						return true;
					}
					return Input.GetKey(trans.KeyCode2);
				}
				return false;
			case InputType.Controller:
				if (LocalInput.GetControllerTriggerDown(trans.ControllerInput) || m_frame == m_inputPressed[trans.InputName])
				{
					m_inputPressed[trans.InputName] = m_frame;
					if (trans.ControllerInput2 == ControllerInputs.None)
					{
						return true;
					}
					return LocalInput.GetControllerTrigger(trans.ControllerInput2);
				}
				return false;
			default:
				return false;
			}
		}
	}
	public enum EntityDataSources
	{
		Invalid,
		Player,
		Mirror,
		OtherPlayer
	}
	public class EntityData
	{
		protected AvatarAnimatorDataContainer m_Cont;

		protected Avatar m_Avatar;

		protected RigManager m_RigManager;

		protected Barcode m_Barcode;

		protected EntityDataSources m_Source;

		protected Mirror m_Mirror = null;

		protected byte m_id;

		private bool valid = false;

		public AvatarAnimatorDataContainer Container => m_Cont;

		public Animator Animator => m_Cont.m_Animator;

		public AvatarAnimatorData Data => m_Cont.m_Data;

		public bool HasAvatarAnimatorData => m_Cont?.m_Data != null;

		public Avatar Avatar => m_Avatar;

		public RigManager RigManager => m_RigManager;

		public Barcode Barcode => m_Barcode;

		public EntityDataSources Source => m_Source;

		public Mirror Mirror => m_Mirror;

		public byte Id => m_id;

		public bool IsValid => valid;

		public static EntityData Create()
		{
			EntityData data = new EntityData();
			data.m_Source = EntityDataSources.Player;
			data.m_RigManager = Player.RigManager;
			SetId(ref data);
			data.UpdateAvatar();
			return data;
		}

		public static EntityData Create(Mirror mirror)
		{
			EntityData data = new EntityData();
			data.m_Source = EntityDataSources.Mirror;
			data.m_Mirror = mirror;
			data.m_RigManager = mirror.rigManager;
			SetId(ref data);
			data.UpdateAvatar();
			return data;
		}

		private static void SetId(ref EntityData data)
		{
			try
			{
				data.m_id = Utils.GetPlayerId(data.m_RigManager);
			}
			catch (Exception ex)
			{
				Logger.Dbg?.Warn(ex.ToString());
				data.m_Source = EntityDataSources.Invalid;
			}
		}

		public void MakeInvalid()
		{
			valid = false;
		}

		protected virtual void SetAvatar()
		{
			EntityDataSources source = m_Source;
			if (1 == 0)
			{
			}
			Avatar avatar = (Avatar)(source switch
			{
				EntityDataSources.Player => Player.Avatar, 
				EntityDataSources.Mirror => m_Mirror.Reflection, 
				_ => m_RigManager.avatar, 
			});
			if (1 == 0)
			{
			}
			m_Avatar = avatar;
		}

		public void UpdateAvatar()
		{
			SetAvatar();
			RigManager rigManager = m_RigManager;
			object barcode;
			if (rigManager == null)
			{
				barcode = null;
			}
			else
			{
				AvatarCrateReference avatarCrate = rigManager.AvatarCrate;
				barcode = ((avatarCrate != null) ? ((ScannableReference)avatarCrate).Barcode : null);
			}
			m_Barcode = (Barcode)barcode;
			if (m_Source != EntityDataSources.Invalid)
			{
				m_Cont = ((Component)m_Avatar).gameObject.GetComponent<AvatarAnimatorDataContainer>();
			}
			if ((Object)null != (Object)(object)m_Cont)
			{
				try
				{
					m_Cont.m_Data = AvatarAnimatorDataDeserializer.Deserialize(m_Cont.m_Version, m_Cont.m_SerializeData);
					Logger.Msg("AvatarAnimator '" + ((Object)Barcode).ToString() + "' Data found version " + m_Cont.m_Version);
				}
				catch (Exception ex)
				{
					Logger.Warn(ex.ToString());
				}
				Logger.Dbg?.Data(m_Cont.m_SerializeData);
			}
			valid = (Object)null != (Object)(object)m_Cont && (Object)null != (Object)(object)m_Cont?.m_Animator;
			Logger.Dbg?.Info(DebugEntityData());
		}

		public string DebugEntityData()
		{
			return $"id:'{m_id}', sc:{m_Source}, valid:{valid}, Rig:'{(Object)null != (Object)(object)m_RigManager}', Avatar:'{(Object)null != (Object)(object)m_Avatar}' {((Object)m_Barcode).ToString()}, Cont:'{(Object)null != (Object)(object)m_Cont}', Anim:'{(Object)null != (Object)(object)m_Cont?.m_Animator}'";
		}
	}
	public static class MirrorScanner
	{
		private static readonly List<EntityData> m_all = new List<EntityData>();

		public static List<EntityData> All => m_all;

		public static event Action<EntityData> OnNew;

		public static event Action<EntityData> OnRemoved;

		public static event Action OnClear;

		public static void Clear()
		{
			m_all.Clear();
			MirrorScanner.OnClear?.Invoke();
		}

		public static void Scan()
		{
			List<Mirror> list = new List<Mirror>((IEnumerable<Mirror>)Object.FindObjectsOfType<Mirror>());
			int num = 0;
			int num2 = 0;
			for (int num3 = m_all.Count - 1; num3 >= 0; num3--)
			{
				EntityData e = m_all[num3];
				if (!((Object)null != (Object)(object)list.Find((Mirror val) => Utils.RefEquals<RigManager>(val.rigManager, e.RigManager))))
				{
					m_all.RemoveAt(num3);
					MirrorScanner.OnRemoved?.Invoke(e);
					num++;
				}
			}
			foreach (Mirror e2 in list)
			{
				if ((Object)null == (Object)(object)e2)
				{
					continue;
				}
				Mirror obj = e2;
				if (!((Object)null == (Object)(object)((obj != null) ? obj.rigManager : null)))
				{
					Mirror obj2 = e2;
					if (!((Object)null == (Object)(object)((obj2 != null) ? obj2.Reflection : null)) && m_all.Find((EntityData entityData2) => Utils.RefEquals<RigManager>(entityData2.RigManager, e2.rigManager)) == null)
					{
						EntityData entityData = EntityData.Create(e2);
						m_all.Add(entityData);
						MirrorScanner.OnNew?.Invoke(entityData);
						num2++;
					}
				}
			}
			if (Logger.Dbg != null && (num != 0 || num2 != 0))
			{
				Logger.Dbg?.Info($"Scanner: Entities {num} removed, {num2} added, {m_all.Count} Total");
			}
		}
	}
	public static class PlayerScanner
	{
		private static EntityData PlayerData;

		public static event Action<EntityData> OnAvatarChange;

		public static event Action<EntityData> OnAvatarSame;

		public static void GetAvatarAnimator()
		{
			Logger.DebugLogger dbg = Logger.Dbg;
			if (dbg != null)
			{
				object[] array = new object[5];
				EntityData playerData = PlayerData;
				object obj;
				if (playerData == null)
				{
					obj = null;
				}
				else
				{
					Barcode barcode = playerData.Barcode;
					obj = ((barcode != null) ? ((Object)barcode).ToString() : null);
				}
				array[0] = obj;
				array[1] = PlayerData?.Source;
				array[2] = (Object)null == (Object)(object)PlayerData?.RigManager;
				Barcode barcode2 = ((ScannableReference)Player.RigManager.AvatarCrate).Barcode;
				array[3] = ((barcode2 != null) ? ((Object)barcode2).ToString() : null);
				AvatarCrateReference avatarCrate = Player.RigManager.AvatarCrate;
				object obj2;
				if (avatarCrate == null)
				{
					obj2 = null;
				}
				else
				{
					AvatarCrate crate = ((CrateReferenceT<AvatarCrate>)(object)avatarCrate).Crate;
					obj2 = ((crate != null) ? ((Scannable)crate).Title : null);
				}
				array[4] = obj2;
				dbg.Data(string.Format("OLD: {0} '{1}' '{2}'  -  NEW:{3} '{4}'", array));
			}
			bool flag = EntityDataSources.Invalid == PlayerData?.Source;
			bool flag2 = ((ScannableReference)Player.RigManager.AvatarCrate).Barcode != PlayerData?.Barcode;
			if (!flag2 || PlayerData == null || flag)
			{
				PlayerData = EntityData.Create();
			}
			else
			{
				PlayerData.UpdateAvatar();
			}
			Logger.Dbg?.Info($"GetPlayerAvatarAnimator hasAvatarChange:{flag2}");
			if (flag2)
			{
				PlayerScanner.OnAvatarChange?.Invoke(PlayerData);
			}
			else
			{
				PlayerScanner.OnAvatarSame?.Invoke(PlayerData);
			}
		}
	}
	public abstract class TimeGate
	{
		public abstract void Reset();

		public abstract bool Now();
	}
	public class UpdateTimeGate : TimeGate
	{
		private readonly int m_init;

		private int m_interval;

		private int m_timer;

		public int Interval
		{
			get
			{
				return m_interval;
			}
			set
			{
				m_interval = value;
			}
		}

		public UpdateTimeGate(int interval, int startAt = 0)
		{
			m_init = startAt;
			m_interval = interval;
			Reset();
		}

		public override void Reset()
		{
			m_timer = m_init;
		}

		public override bool Now()
		{
			m_timer = (m_timer + 1) % m_interval;
			return m_timer == 0;
		}
	}
	public class DelayTimeGate : TimeGate
	{
		private readonly double m_interval;

		private DateTime m_timer;

		public DelayTimeGate(double sec)
		{
			m_interval = sec;
			Reset();
		}

		public override bool Now()
		{
			if (DateTime.Now > m_timer)
			{
				m_timer = m_timer.AddSeconds(m_interval);
				if (DateTime.Now > m_timer)
				{
					Reset();
				}
				return true;
			}
			return false;
		}

		public override void Reset()
		{
			m_timer = DateTime.Now.AddSeconds(m_interval);
		}
	}
	[Serializable]
	public class AvatarAnimatorDataContainer : MonoBehaviour
	{
		public const string m_CurrentApiVersion = "1.0";

		public Animator m_Animator;

		public AvatarAnimatorData m_Data;

		public string m_Version;

		public string m_SerializeData;

		public void PopulateData(Animator anim, AvatarAnimatorData data)
		{
			m_Animator = anim;
			m_Data = data;
			m_Version = "1.0";
		}

		public void SerializeData()
		{
			if (m_Data == null)
			{
				throw new Exception("Cannot Serialize null Data");
			}
			m_SerializeData = JsonConvert.SerializeObject((object)m_Data, (Formatting)0);
		}
	}
	public enum InputType
	{
		Unset,
		Keyboard,
		Controller
	}
	public enum ConditionMode
	{
		Unset,
		If,
		IfNot,
		Greater,
		Less,
		Equals,
		NotEqual
	}
	public enum ConditionType
	{
		Unset,
		Input,
		Random,
		Health,
		Timer,
		WaitEndClip,
		Cyclic
	}
	public enum ControllerInputs
	{
		None,
		A,
		B,
		X,
		Y,
		LeftGrip,
		RightGrip,
		LeftTrigger,
		RightTrigger,
		Menu,
		SecondaryMenu,
		LeftThumbStick,
		RightThumbStick,
		LeftTouchPad,
		RightTouchPad
	}
	[Serializable]
	public class StateNode
	{
		public float ClipDuration;

		public bool ClipIsLooping;

		public float Speed;

		public List<Transition> Transitions;
	}
	[Serializable]
	public class Transition
	{
		public string NextState;

		public float Duration;

		public float ExitTime;

		public bool HasExitTime;

		public List<TransitionCondition> Conditions;
	}
	[Serializable]
	public class TransitionCondition
	{
		public string Name;

		public ConditionType Type;

		public ConditionMode Mode;

		public float Threshold;
	}
	[Serializable]
	public class TransitionConditionData
	{
		public ConditionType Type;

		public int Min;

		public int Max;

		public List<ConditionInput> Inputs;
	}
	[Serializable]
	public class ConditionInput
	{
		public InputType Type;

		public string InputName;

		public KeyCode KeyCode;

		public ControllerInputs ControllerInput;

		public string InputName2;

		public KeyCode KeyCode2;

		public ControllerInputs ControllerInput2;
	}
	[Serializable]
	public class LayerData
	{
		public string Name;

		public Dictionary<string, StateNode> States;

		public int LayerIndex;

		public string StartState;
	}
	[Serializable]
	public class AvatarAnimatorData
	{
		public List<LayerData> ListLayer;

		public Dictionary<string, TransitionConditionData> TransitionsData;

		public string Date;
	}
	public delegate bool FuncTmp();
	public delegate void Func();
	public static class UpdateSystem
	{
		private static readonly Dictionary<string, Func> ToDoLaterOnce = new Dictionary<string, Func>();

		private static readonly Dictionary<string, FuncTmp> ToDoLaterTmp = new Dictionary<string, FuncTmp>();

		private static readonly Dictionary<string, Func> ToDoLater = new Dictionary<string, Func>();

		public static void CallLaterOnce(string name, Func func)
		{
			ToDoLaterOnce.Add(name, func);
		}

		public static void CallLaterOnce(Func func)
		{
			CallLaterOnce($"{func.GetHashCode()}", func);
		}

		public static bool RemoveLater(string name)
		{
			return ToDoLaterOnce.Remove(name);
		}

		public static bool RemoveLater(Func func)
		{
			return RemoveLater($"{func.GetHashCode()}");
		}

		public static void CallLaterTmp(string name, FuncTmp func)
		{
			ToDoLaterTmp.Add(name, func);
		}

		public static void CallLaterTmp(FuncTmp func)
		{
			CallLaterTmp($"{func.GetHashCode()}", func);
		}

		public static bool RemoveTmp(string name)
		{
			return ToDoLaterTmp.Remove(name);
		}

		public static bool RemoveTmp(FuncTmp func)
		{
			return RemoveTmp($"{func.GetHashCode()}");
		}

		public static void CallLater(string name, Func func)
		{
			ToDoLater.Add(name, func);
		}

		public static void CallLater(Func func)
		{
			CallLater($"{func.GetHashCode()}", func);
		}

		public static bool Remove(string name)
		{
			return ToDoLater.Remove(name);
		}

		public static bool Remove(Func func)
		{
			return Remove($"{func.GetHashCode()}");
		}

		public static void Update()
		{
			if (ToDoLaterOnce.Count > 0)
			{
				foreach (KeyValuePair<string, Func> item in ToDoLaterOnce)
				{
					try
					{
						item.Value();
					}
					catch (Exception ex)
					{
						Logger.Err(ex.ToString());
					}
				}
				ToDoLaterOnce.Clear();
			}
			if (ToDoLaterTmp.Count > 0)
			{
				foreach (KeyValuePair<string, FuncTmp> item2 in ToDoLaterTmp)
				{
					try
					{
						if (item2.Value())
						{
							ToDoLaterTmp.Remove(item2.Key);
						}
					}
					catch (Exception ex2)
					{
						Logger.Err(ex2.ToString());
					}
				}
			}
			if (ToDoLater.Count <= 0)
			{
				return;
			}
			foreach (KeyValuePair<string, Func> item3 in ToDoLater)
			{
				try
				{
					item3.Value();
				}
				catch (Exception ex3)
				{
					Logger.Err(ex3.ToString());
				}
			}
		}
	}
	public delegate byte PlayerIdGetterFunc(RigManager rig);
	public delegate bool FindFunc<in T>(T arg);
	public static class Utils
	{
		private static readonly Random rnd = new Random();

		public static PlayerIdGetterFunc GetPlayerId = (RigManager _) => 0;

		public static bool Is(ConditionMode? ope, float value, float threshold = 0f)
		{
			if (1 == 0)
			{
			}
			bool result = ope switch
			{
				ConditionMode.Greater => value > threshold, 
				ConditionMode.Less => value < threshold, 
				ConditionMode.If => 1f == value, 
				ConditionMode.IfNot => 0f == value, 
				ConditionMode.Equals => (int)value == (int)threshold, 
				ConditionMode.NotEqual => (int)value != (int)threshold, 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public static bool Is(ConditionMode? ope, int value, int threshold = 0)
		{
			if (1 == 0)
			{
			}
			bool result = ope switch
			{
				ConditionMode.Greater => value > threshold, 
				ConditionMode.Less => value < threshold, 
				ConditionMode.If => 1 == value, 
				ConditionMode.IfNot => value == 0, 
				ConditionMode.Equals => value == threshold, 
				ConditionMode.NotEqual => value != threshold, 
				_ => false, 
			};
			if (1 == 0)
			{
			}
			return result;
		}

		public static DateTime DateTimeNowPlusSecs(double sec)
		{
			return DateTime.Now.AddSeconds(sec);
		}

		public static int RandomInt(int min, int max)
		{
			return rnd.Next(min, max);
		}

		public static bool RefEquals<T>(T obj1, T obj2)
		{
			return (object)obj1 == (object)obj2;
		}

		public static float ComputNTime(DateTime now, DateTime playAt, float? m_nTime, float? m_Duration, float? m_Speed)
		{
			float num = (float)(now - playAt).TotalSeconds;
			float num2 = m_nTime.GetValueOrDefault();
			float valueOrDefault = m_Duration.GetValueOrDefault();
			float num3 = m_Speed ?? 1f;
			Logger.Dbg?.Info($"Tdiff:{num} nTime:{num2} d:{valueOrDefault} s:{num3}");
			if (valueOrDefault != 0f && num3 != 0f)
			{
				num2 += num / (valueOrDefault * (1f / num3));
			}
			Logger.Dbg?.Info($"nTime:{num2}");
			return num2;
		}

		public static void AddOrReplace<TKey, TValue>(Dictionary<TKey, TValue> dic, TKey key, TValue value)
		{
			if (dic.ContainsKey(key))
			{
				dic[key] = value;
			}
			else
			{
				dic.Add(key, value);
			}
		}
	}
	public static class Debug
	{
		public static void GetAvatarMetadata(Avatar avatar)
		{
			if (!((Object)(object)avatar == (Object)null))
			{
				RigManager componentInParent = ((Component)avatar).GetComponentInParent<RigManager>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.AvatarCrate != null)
				{
					AvatarCrate crate = ((CrateReferenceT<AvatarCrate>)(object)componentInParent.AvatarCrate).Crate;
					string text = ((Object)((Scannable)crate).Barcode).ToString();
					string title = ((Scannable)crate).Title;
					Pallet pallet = ((Crate)crate).Pallet;
					string text2 = (((Object)(object)pallet != (Object)null) ? ((Scannable)pallet).Title : "Inconnue");
					Logger.Dbg?.Debug("Avatar actif : " + title + " (Barcode: " + text + ") | Palette: " + text2);
				}
				else
				{
					Logger.Dbg?.Debug("Avatar actif : " + ((Object)((Component)avatar).gameObject).name);
				}
			}
		}

		public static void InspectGameObject(GameObject target)
		{
			Transform transform = target.transform;
			for (int i = 0; i < transform.childCount; i++)
			{
				Transform child = transform.GetChild(i);
				Logger.Dbg?.Debug("Child IL2CPP : " + ((Object)child).name);
			}
			foreach (Component component in target.GetComponents<Component>())
			{
				if (!((Object)(object)component == (Object)null))
				{
					Type il2CppType = ((Object)component).GetIl2CppType();
					Logger.Dbg?.Debug(" Component IL2CPP : " + il2CppType.FullName);
				}
			}
			foreach (Component item in target.GetComponentsInParent<Component>())
			{
				if (!((Object)(object)item == (Object)null))
				{
					Type il2CppType2 = ((Object)item).GetIl2CppType();
					Logger.Dbg?.Debug(" Parent Component IL2CPP : " + il2CppType2.FullName);
				}
			}
		}

		public static string ToString(HandSchematic hand)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00d9: Unknown result type (might be due to invalid IL or missing references)
			return $"{hand.thumb1} ({hand.thumb2} {hand.thumb3})  {hand.index1} ({hand.index2} {hand.index3})   {hand.middle1} ({hand.middle2} {hand.middle3})   {hand.ring1} ({hand.ring2} {hand.ring3})   {hand.pinky1} ({hand.pinky2} {hand.pinky3})";
		}
	}
}
namespace AvatarAnimator.FusionLab
{
	public class AvatarAnimatorFusionModule : Module
	{
		private static bool isOnline = false;

		private static readonly Dictionary<byte, OtherPlayerAnimator> players = new Dictionary<byte, OtherPlayerAnimator>();

		private static readonly Dictionary<byte, NetworkPlayer> waitingPlayers = new Dictionary<byte, NetworkPlayer>();

		private static bool m_levelLoading = false;

		public override string Name => "AvatarAnimator";

		public override string Author => "Daedalus";

		public override Version Version => new Version("1.0.0");

		public override ConsoleColor Color => ConsoleColor.DarkGreen;

		public static bool IsLevelLoading => m_levelLoading;

		protected override void OnModuleRegistered()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Expected O, but got Unknown
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Expected O, but got Unknown
			Logger.Msg("AvatarAnimatorFusionModule registered");
			Utils.GetPlayerId = delegate(RigManager rig)
			{
				if (!isOnline)
				{
					return 0;
				}
				NetworkPlayer val = default(NetworkPlayer);
				if (!NetworkPlayerManager.TryGetPlayer(rig, ref val))
				{
					throw new Exception("Player RigManager with Avatar " + ((Object)((ScannableReference)rig.AvatarCrate).Barcode).ToString() + " doesn't have a Player Id");
				}
				return val.PlayerID.SmallID;
			};
			ModuleMessageManager.RegisterHandler<PlayerStateChangeMessageModule>();
			MirrorScanner.OnNew += OnNew;
			MirrorScanner.OnRemoved += OnRemoved;
			MirrorScanner.OnClear += OnClear;
			MultiplayerHooking.OnPlayerJoined += new PlayerUpdate(OnPlayerJoined);
			MultiplayerHooking.OnPlayerLeft += new PlayerUpdate(OnPlayerLeft);
			MultiplayerHooking.OnStartedServer += new ServerEvent(OnJoinedServer);
			MultiplayerHooking.OnJoinedServer += new ServerEvent(OnJoinedServer);
			MultiplayerHooking.OnDisconnected += new ServerEvent(OnDisconnected);
			PlayerAnimator.OnAvatarStateChanged += OnAvatarStateChanged;
			PlayerID.OnMetadataChangedEvent += OnPlayerMetadataChangedEvent;
			Hooking.OnLevelLoaded += OnLevelLoaded;
			NetworkPlayer.OnNetworkRigCreated += OnNetworkRigCreated;
			NetworkPlayer.OnNetworkPlayerRegistered += OnNetworkPlayerRegistered;
			CorePrivate.SimplePlayerMonitoring();
		}

		protected override void OnModuleUnregistered()
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			Logger.Msg("Module unregistered");
			players.Clear();
			PlayerStateChangeMessageModule.WaitingList.Clear();
			MirrorScanner.OnNew -= OnNew;
			MirrorScanner.OnRemoved -= OnRemoved;
			MirrorScanner.OnClear -= OnClear;
			MultiplayerHooking.OnPlayerJoined -= new PlayerUpdate(OnPlayerJoined);
			MultiplayerHooking.OnPlayerLeft -= new PlayerUpdate(OnPlayerLeft);
			MultiplayerHooking.OnJoinedServer -= new ServerEvent(OnJoinedServer);
			MultiplayerHooking.OnDisconnected -= new ServerEvent(OnDisconnected);
			PlayerAnimator.OnAvatarStateChanged -= OnAvatarStateChanged;
			PlayerID.OnMetadataChangedEvent -= OnPlayerMetadataChangedEvent;
			Hooking.OnLevelLoaded -= OnLevelLoaded;
			NetworkPlayer.OnNetworkRigCreated -= OnNetworkRigCreated;
			NetworkPlayer.OnNetworkPlayerRegistered -= OnNetworkPlayerRegistered;
		}

		public static void ChangeOtherPlayerState(OtherPlayerStates states)
		{
			if (players.ContainsKey(states.m_smallId))
			{
				Logger.Dbg?.Info("Change other Player animator state");
				players[states.m_smallId].SetAnimatorState(states);
			}
		}

		public static NetworkPlayer FindPlayer(FindFunc<NetworkPlayer> func)
		{
			foreach (NetworkPlayer player in NetworkPlayer.Players)
			{
				if (func(player))
				{
					return player;
				}
			}
			return null;
		}

		private void OnNew(EntityData data)
		{
			if (players.ContainsKey(data.Id))
			{
				OtherPlayerAnimator otherPlayerAnimator = players[data.Id];
				if (!otherPlayerAnimator.IsMe())
				{
					Logger.Dbg?.Info($"Add Mirror to Other Player {data.Id}");
					otherPlayerAnimator.AddMirror(data);
				}
			}
		}

		private void OnRemoved(EntityData data)
		{
			if (players.ContainsKey(data.Id))
			{
				OtherPlayerAnimator otherPlayerAnimator = players[data.Id];
				otherPlayerAnimator.RemoveMirror(data);
			}
		}

		private void OnClear()
		{
			foreach (KeyValuePair<byte, OtherPlayerAnimator> player in players)
			{
				player.Value.ClearMirrors();
			}
		}

		private void OnPlayerJoined(PlayerID id)
		{
			Logger.Dbg?.Debug("OnPlayerJoined");
		}

		private void OnPlayerLeft(PlayerID id)
		{
			Logger.Dbg?.Debug("OnPlayerLeft");
			Logger.Dbg?.Info($"Player '{id.SmallID}' Left");
			if (!id.IsMe)
			{
				players.Remove(id.SmallID);
			}
		}

		private void OnJoinedServer()
		{
			Logger.Dbg?.Debug("OnJoinedServer");
			isOnline = true;
			CorePrivate.MultiPlayerMonitoring();
			foreach (NetworkPlayer player in NetworkPlayer.Players)
			{
				Logger.Dbg?.Info($"Player '{player.PlayerID.SmallID}'");
			}
		}

		private void OnDisconnected()
		{
			Logger.Dbg?.Debug("OnDisconnected");
			isOnline = false;
			players.Clear();
			CorePrivate.SimplePlayerMonitoring();
		}

		private void OnAvatarStateChanged(PlayerStateChange change)
		{
			if (isOnline)
			{
				PlayerStateChangeMessageModule.SendMessage(new OtherPlayerStates(PlayerAnimator.Id, change));
			}
		}

		private void OnPlayerMetadataChangedEvent(PlayerID playerId, string key, string value)
		{
			Logger.DebugLogger dbg = Logger.Dbg;
			if (dbg != null)
			{
				PlayerID obj = playerId;
				dbg.Debug($"id:{((obj != null) ? new byte?(obj.SmallID) : ((byte?)null))} key:'{key}' value:'{value}'");
			}
			if (!(key == "AvatarTitle"))
			{
				if (!(key == "Loading") || !playerId.IsMe)
				{
					return;
				}
				m_levelLoading = "true" == value;
				Logger.Dbg?.Info($"Level loading = {IsLevelLoading}");
				if (IsLevelLoading)
				{
					return;
				}
				PlayerScanner.GetAvatarAnimator();
				if (waitingPlayers.Count > 0)
				{
					foreach (KeyValuePair<byte, NetworkPlayer> waitingPlayer in waitingPlayers)
					{
						AddOrUpdatePlayer(waitingPlayer.Value);
					}
				}
				foreach (KeyValuePair<byte, OtherPlayerAnimator> player in players)
				{
					player.Value.OnAvatarChanged();
				}
				Logger.Dbg?.Info($"Level finish to loading, use {PlayerStateChangeMessageModule.WaitingList.Count} stored messages");
				foreach (OtherPlayerStates waiting in PlayerStateChangeMessageModule.WaitingList)
				{
					ChangeOtherPlayerState(waiting);
				}
				PlayerStateChangeMessageModule.WaitingList.Clear();
			}
			else
			{
				if (IsLevelLoading || !players.ContainsKey(playerId.SmallID))
				{
					return;
				}
				if (playerId.IsMe)
				{
					Logger.Dbg?.Info("Player avatar changed");
					CorePrivate.UpdatePlayerAvatar();
					return;
				}
				UpdateSystem.CallLaterOnce(delegate
				{
					Logger.Dbg?.Info($"Other Player '{playerId.SmallID}' avatar changed");
					players[playerId.SmallID].OnAvatarChanged();
				});
			}
		}

		private void OnLevelLoaded(LevelInfo _)
		{
			Logger.Dbg?.Debug("OnLevelLoaded");
		}

		private void OnNetworkRigCreated(NetworkPlayer player, RigManager _2)
		{
			Logger.Dbg?.Debug("OnNetworkRigCreated");
			if (IsLevelLoading)
			{
				Utils.AddOrReplace(waitingPlayers, player.PlayerID.SmallID, player);
				return;
			}
			UpdateSystem.CallLaterOnce(delegate
			{
				if (!IsLevelLoading)
				{
					AddOrUpdatePlayer(player);
				}
			});
		}

		private void OnNetworkPlayerRegistered(NetworkPlayer player)
		{
			Logger.Dbg?.Debug("OnNetworkPlayerRegistered");
			if (IsLevelLoading)
			{
				Utils.AddOrReplace(waitingPlayers, player.PlayerID.SmallID, player);
				return;
			}
			UpdateSystem.CallLaterOnce(delegate
			{
				if (!IsLevelLoading)
				{
					AddOrUpdatePlayer(player);
					if (!player.PlayerID.IsMe)
					{
						List<PlayerStateChange> playerStates = PlayerAnimator.GetPlayerStates();
						if (playerStates.Count > 0)
						{
							PlayerStateChangeMessageModule.SendMessageTo(player.PlayerID.SmallID, new OtherPlayerStates(PlayerAnimator.Id, null, playerStates));
						}
					}
				}
			});
		}

		private void AddOrUpdatePlayer(NetworkPlayer player)
		{
			byte smallID = player.PlayerID.SmallID;
			if (players.ContainsKey(smallID))
			{
				Logger.Dbg?.Info($"Player '{smallID}' update");
				players.Remove(smallID);
			}
			else
			{
				Logger.Dbg?.Info($"Player '{smallID}' Join");
			}
			players.Add(smallID, new OtherPlayerAnimator(player, player.PlayerID));
		}
	}
	public static class AvatarAnimatorFusionModuleLoader
	{
		public static void LoadModule()
		{
			ModuleManager.RegisterModule<AvatarAnimatorFusionModule>();
		}
	}
	[Serializable]
	public class OtherPlayerStates
	{
		[JsonProperty("SmallId")]
		public byte m_smallId;

		[JsonProperty("States")]
		public List<PlayerStateChange> m_States = new List<PlayerStateChange>();

		public OtherPlayerStates(byte smallId, PlayerStateChange change = null, List<PlayerStateChange> states = null)
		{
			m_smallId = smallId;
			if (change != null)
			{
				m_States.Add(change);
			}
			if (states != null)
			{
				m_States.AddRange(states);
			}
		}

		public static string Serialize(OtherPlayerStates obj)
		{
			return JsonConvert.SerializeObject((object)obj, (Formatting)0);
		}

		public static OtherPlayerStates Deserialize(string json)
		{
			return JsonConvert.DeserializeObject<OtherPlayerStates>(json);
		}
	}
	public class OtherPlayerState
	{
		public int m_Layer;

		public string m_State;

		public OtherPlayerState(int layer, string state)
		{
			m_Layer = layer;
			m_State = state;
		}
	}
	public class OtherPlayerAnimator
	{
		private readonly List<EntityData> m_mirrorAnimators = new List<EntityData>();

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

		private readonly OtherPlayerData m_player = null;

		public OtherPlayerAnimator(NetworkPlayer player, PlayerID playerId)
		{
			m_player = OtherPlayerData.Create(player, playerId);
			UpdateStates();
		}

		public void SetAnimatorState(OtherPlayerStates states)
		{
			if (states == null || !m_player.IsValid)
			{
				Logger.Dbg?.Warn($"Cannot change state {states == null} {!m_player.IsValid}");
				Logger.Dbg?.Info(m_player.DebugEntityData());
				return;
			}
			DateTime now = DateTime.Now;
			foreach (PlayerStateChange state in states.m_States)
			{
				float num = Utils.ComputNTime(now, state.now, state.m_nTime, state.m_Duration, state.m_Speed);
				m_player.Animator.Play(state.m_State, state.m_Layer, num);
				foreach (EntityData mirrorAnimator in m_mirrorAnimators)
				{
					mirrorAnimator.Animator.Play(state.m_State, state.m_Layer, num);
				}
				Logger.Dbg?.Info("OtherPlayerAnimator PlayState");
				m_States[state.m_Layer].m_State = state.m_State;
			}
		}

		public void OnAvatarChanged()
		{
			m_player.UpdateAvatar();
			foreach (EntityData mirrorAnimator in m_mirrorAnimators)
			{
				mirrorAnimator.UpdateAvatar();
			}
			UpdateStates();
		}

		private void UpdateStates()
		{
			m_States.Clear();
			if (!m_player.IsValid)
			{
				return;
			}
			foreach (LayerData item in m_player.Data.ListLayer)
			{
				m_States.Add(item.LayerIndex, new OtherPlayerState(item.LayerIndex, item.StartState));
			}
		}

		public void AddMirror(EntityData data)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			m_mirrorAnimators.Add(data);
			if (!m_player.IsValid)
			{
				return;
			}
			foreach (KeyValuePair<int, OtherPlayerState> state in m_States)
			{
				AnimatorStateInfo currentAnimatorStateInfo = m_player.Animator.GetCurrentAnimatorStateInfo(state.Value.m_Layer);
				data.Animator.Play(state.Value.m_State, state.Value.m_Layer, ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime);
				Logger.Dbg?.Info($"AddMirror {state.Value.m_State} {state.Value.m_Layer} {((AnimatorStateInfo)(ref currentAnimatorStateInfo)).normalizedTime}");
			}
		}

		public void RemoveMirror(EntityData data)
		{
			m_mirrorAnimators.Remove(data);
		}

		public void ClearMirrors()
		{
			m_mirrorAnimators.Clear();
		}

		public bool IsMe()
		{
			return m_player.IsMe();
		}
	}
	public class OtherPlayerData : EntityData
	{
		protected PlayerID m_PlayerId;

		protected NetworkPlayer m_NetworkPlayer;

		public static OtherPlayerData Create(NetworkPlayer player, PlayerID id)
		{
			OtherPlayerData otherPlayerData = new OtherPlayerData();
			otherPlayerData.m_Source = EntityDataSources.OtherPlayer;
			otherPlayerData.m_PlayerId = id;
			otherPlayerData.m_NetworkPlayer = player;
			otherPlayerData.m_RigManager = player.RigRefs.RigManager;
			otherPlayerData.m_id = otherPlayerData.m_PlayerId.SmallID;
			otherPlayerData.UpdateAvatar();
			return otherPlayerData;
		}

		public bool IsMe()
		{
			return m_PlayerId.IsMe;
		}

		protected override void SetAvatar()
		{
			m_Avatar = m_RigManager.avatar;
		}
	}
	public class PlayerStateChangeMessageModule : ModuleMessageHandler
	{
		public class MyNetSerializable : INetSerializable
		{
			public string m_data;

			public int? GetSize()
			{
				return SizeExtensions.GetSize(m_data);
			}

			public void Serialize(INetSerializer serializer)
			{
				serializer.SerializeValue(ref m_data);
			}
		}

		private static readonly List<OtherPlayerStates> m_waitingList = new List<OtherPlayerStates>();

		public static List<OtherPlayerStates> WaitingList => m_waitingList;

		public static void SendMessage(OtherPlayerStates d)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			MyNetSerializable myNetSerializable = new MyNetSerializable
			{
				m_data = OtherPlayerStates.Serialize(d)
			};
			Logger.Dbg?.Data("Msg sent '" + myNetSerializable.m_data + "'");
			MessageRelay.RelayModule<PlayerStateChangeMessageModule, MyNetSerializable>(myNetSerializable, new MessageRoute((RelayType)3, (NetworkChannel)0));
		}

		public static void SendMessageTo(byte smallId, OtherPlayerStates d)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			MyNetSerializable myNetSerializable = new MyNetSerializable
			{
				m_data = OtherPlayerStates.Serialize(d)
			};
			Logger.Dbg?.Data($"Msg sent '{myNetSerializable.m_data}' to {smallId}");
			MessageRelay.RelayModule<PlayerStateChangeMessageModule, MyNetSerializable>(myNetSerializable, new MessageRoute(smallId, (NetworkChannel)0));
		}

		protected override void OnHandleMessage(ReceivedMessage received)
		{
			MyNetSerializable myNetSerializable = ((ReceivedMessage)(ref received)).ReadData<MyNetSerializable>();
			OtherPlayerStates otherPlayerStates = OtherPlayerStates.Deserialize(myNetSerializable.m_data);
			Logger.Dbg?.Data($"Msg received '{myNetSerializable.m_data}' from {otherPlayerStates.m_smallId}");
			if (PlayerAnimator.Id != otherPlayerStates.m_smallId)
			{
				if (AvatarAnimatorFusionModule.IsLevelLoading)
				{
					Logger.Dbg?.Info("Level didn't finish to load, store Message data");
					m_waitingList.Add(otherPlayerStates);
				}
				else
				{
					AvatarAnimatorFusionModule.ChangeOtherPlayerState(otherPlayerStates);
				}
			}
		}
	}
}
namespace AvatarAnimator.Deserialize
{
	public static class AvatarAnimatorDataDeserializer
	{
		public static AvatarAnimatorData Deserialize(string version, string data)
		{
			if (data == null || "" == data)
			{
				throw new Exception("Cannot Deserialize null or empty data");
			}
			if (1 == 0)
			{
			}
			if (version == "1.0")
			{
				AvatarAnimatorData result = JsonConvert.DeserializeObject<AvatarAnimatorData>(data);
				if (1 == 0)
				{
				}
				return result;
			}
			throw new Exception("Unsuported Data version '" + version + "'");
		}
	}
}