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 + "'");
}
}
}