using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AdvancedAvatarControl;
using AdvancedAvatarControl.BoneMenu;
using AdvancedAvatarControl.Messages;
using AdvancedAvatarControl.Patches;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.BoneMenu.Elements;
using BoneLib.Notifications;
using HarmonyLib;
using LabFusion.Data;
using LabFusion.Network;
using LabFusion.Representation;
using LabFusion.SDK.Modules;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using SLZ.Rig;
using SLZ.VRMK;
using UnhollowerBaseLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyDescription("More control over your avatar!")]
[assembly: AssemblyCopyright("Developed by Checkerboard")]
[assembly: AssemblyTrademark(null)]
[assembly: MelonInfo(typeof(MelonMod), "Advanced Avatar Control", "1.1.1", "Checkerboard", null)]
[assembly: MelonColor(ConsoleColor.Cyan)]
[assembly: ModuleInfo(typeof(FusionModule), "AdvancedAvatarContol", "1.0.0", "Checkerboard", null, true, ConsoleColor.Cyan)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonOptionalDependencies(new string[] { "labfusion" })]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("AdvancedAvatarControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+615480adfaee572cdc857b9c992ec3d172394506")]
[assembly: AssemblyProduct("AdvancedAvatarControl")]
[assembly: AssemblyTitle("More control over your avatar!")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace AdvancedAvatarControl
{
internal class MelonMod : MelonMod
{
internal const string Name = "Advanced Avatar Control";
internal const string Description = "More control over your avatar!";
internal const string Author = "Checkerboard";
internal const string Company = null;
internal const string Version = "1.1.1";
internal const string DownloadLink = null;
internal static bool FusionInstalled;
public override void OnEarlyInitializeMelon()
{
((MelonBase)this).OnEarlyInitializeMelon();
}
public override void OnInitializeMelon()
{
Prefs.Initialize();
ModuleHandler.LoadModule(Assembly.GetExecutingAssembly());
}
public override void OnLateInitializeMelon()
{
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected O, but got Unknown
AdvancedAvatarControl.BoneMenu.BoneMenu.CreateBoneMenu();
Hooking.OnLevelInitialized += AddEyeMovement;
Hooking.OnSwitchAvatarPostfix += AdvancedAvatarControl.BoneMenu.BoneMenu.OnSwitchAvatar;
MultiplayerHooking.OnPlayerRepCreated += new RigManagerEvent(AddRepEyeMovement);
FusionInstalled = HelperMethods.CheckIfAssemblyLoaded("labfusion");
}
public void AddEyeMovement(LevelInfo levelInfo)
{
if ((Object)(object)((Component)Player.playerHead).gameObject.GetComponent<PlayerEyeController>() != (Object)null)
{
MelonLogger.Msg("PlayerEyeController already exists");
}
else
{
((Component)Player.playerHead).gameObject.AddComponent<PlayerEyeController>();
}
}
public void AddRepEyeMovement(RigManager playerRep)
{
((Component)((Rig)playerRep.physicsRig).m_head).gameObject.AddComponent<RepEyeController>();
}
}
public static class ModuleInfo
{
public const string Name = "AdvancedAvatarContol";
public const string Version = "1.0.0";
public const string Author = "Checkerboard";
public const string Abbreviation = null;
public const bool AutoRegister = true;
public const ConsoleColor Color = ConsoleColor.Cyan;
}
public class FusionModule : Module
{
public static FusionModule Instance { get; private set; }
public override void OnModuleLoaded()
{
Instance = this;
((Module)this).LoggerInstance.Log("Module was loaded!", ConsoleColor.White);
}
public void SendBlendBoneMessage(float boneData, int boneIndex)
{
FusionWriter val = FusionWriter.Create();
try
{
using BlendBones.BasicNumericData basicNumericData = BlendBones.BasicNumericData.Create(boneIndex, boneData, PlayerIdManager.LocalSmallId);
val.Write<BlendBones.BasicNumericData>(basicNumericData);
FusionMessage val2 = FusionMessage.ModuleCreate<BlendBones.BasicNumericMessage>(val);
try
{
MessageSender.SendToServer((NetworkChannel)0, val2);
}
finally
{
((IDisposable)val2)?.Dispose();
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
}
public static class Prefs
{
public static readonly MelonPreferences_Category MainCategory = MelonPreferences.CreateCategory("AdvancedAvatarControl");
public static MelonPreferences_Entry<float> EyeMovementSpeed;
public static void Initialize()
{
EyeMovementSpeed = MainCategory.GetEntry<float>("Eye Movement Speed") ?? MainCategory.CreateEntry<float>("Eye Movement Speed", 10f, "Eye Movement Speed", (string)null, false, false, (ValueValidator)null, (string)null);
MainCategory.SetFilePath(MelonUtils.UserDataDirectory + "/AdvancedAvatarControl.cfg");
MainCategory.SaveToFile(false);
}
}
[RegisterTypeInIl2Cpp]
public class PlayerEyeController : MonoBehaviour
{
private Quaternion targetRotation;
private void Start()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
targetRotation = ((Component)this).transform.rotation;
}
private void Update()
{
//IL_000b: 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_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
Quaternion rotation = ((Component)this).gameObject.transform.rotation;
float num = 0f;
if (Time.timeScale != 0f)
{
num = Prefs.EyeMovementSpeed.Value * Time.deltaTime / Time.timeScale;
}
targetRotation = Quaternion.Lerp(targetRotation, rotation, num);
((Component)this).transform.rotation = targetRotation;
}
public PlayerEyeController(IntPtr ptr)
: base(ptr)
{
}
}
[RegisterTypeInIl2Cpp]
public class RepEyeController : MonoBehaviour
{
private Quaternion targetRotation;
private void Start()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
targetRotation = ((Component)this).transform.rotation;
}
private void Update()
{
//IL_000b: 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_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
Quaternion rotation = ((Component)this).gameObject.transform.rotation;
float num = 0f;
if (Time.timeScale != 0f)
{
num = Prefs.EyeMovementSpeed.Value * Time.deltaTime / Time.timeScale;
}
targetRotation = Quaternion.Lerp(targetRotation, rotation, num);
((Component)this).transform.rotation = targetRotation;
}
public RepEyeController(IntPtr ptr)
: base(ptr)
{
}
}
}
namespace AdvancedAvatarControl.Patches
{
[HarmonyPatch(typeof(Mirror), "OnTriggerEnter")]
public class MirrorPatch
{
public static void Postfix(Mirror __instance, Collider c)
{
MirrorExtensions.UpdateMirror();
}
}
public class MirrorExtensions
{
public static void UpdateMirror()
{
if ((Object)(object)AdvancedAvatarControl.BoneMenu.BoneMenu.SelectedMeshRenderer == (Object)null)
{
return;
}
foreach (Avatar item in Object.FindObjectsOfType<Avatar>())
{
if (!(((Object)item).name == ((Object)((Component)Player.GetCurrentAvatar()).gameObject).name))
{
continue;
}
SkinnedMeshRenderer componentInChildren = ((Component)item).gameObject.GetComponentInChildren<SkinnedMeshRenderer>();
if (!((Object)(object)componentInChildren != (Object)null) || !((Object)(object)componentInChildren.sharedMesh != (Object)null))
{
continue;
}
int blendShapeCount = componentInChildren.sharedMesh.blendShapeCount;
foreach (int item2 in Enumerable.Range(0, blendShapeCount))
{
float blendShapeWeight = AdvancedAvatarControl.BoneMenu.BoneMenu.SelectedMeshRenderer.GetBlendShapeWeight(item2);
componentInChildren.sharedMesh.GetBlendShapeName(item2);
componentInChildren.SetBlendShapeWeight(item2, blendShapeWeight);
}
}
}
}
}
namespace AdvancedAvatarControl.Messages
{
public class BlendBones
{
public class BasicNumericData : IFusionSerializable, IDisposable
{
public int intData;
public float floatData;
public byte shortId;
public void Dispose()
{
GC.SuppressFinalize(this);
}
public void Serialize(FusionWriter writer)
{
writer.Write(intData);
writer.Write(floatData);
writer.Write(shortId);
}
public void Deserialize(FusionReader reader)
{
intData = reader.ReadInt32();
floatData = reader.ReadSingle();
shortId = reader.ReadByte();
}
public static BasicNumericData Create(int intData, float floatData, byte shortId)
{
return new BasicNumericData
{
intData = intData,
floatData = floatData,
shortId = shortId
};
}
}
public class BasicNumericMessage : ModuleMessageHandler
{
public override void HandleMessage(byte[] bytes, bool isServerHandled = false)
{
FusionReader val = FusionReader.Create(bytes);
try
{
using BasicNumericData basicNumericData = val.ReadFusionSerializable<BasicNumericData>();
if (NetworkInfo.IsServer && isServerHandled)
{
FusionMessage val2 = FusionMessage.ModuleCreate<BasicNumericMessage>(bytes);
try
{
MessageSender.BroadcastMessage((NetworkChannel)0, val2);
return;
}
finally
{
((IDisposable)val2)?.Dispose();
}
}
int intData = basicNumericData.intData;
float floatData = basicNumericData.floatData;
byte shortId = basicNumericData.shortId;
Avatar val3;
if (shortId == PlayerIdManager.LocalSmallId)
{
val3 = Player.GetCurrentAvatar();
}
else
{
PlayerRep val4 = default(PlayerRep);
PlayerRepManager.TryGetPlayerRep(shortId, ref val4);
val3 = val4.RigReferences.RigManager.avatar;
}
if ((Object)(object)val3 != (Object)null)
{
((Component)val3).gameObject.GetComponentInChildren<SkinnedMeshRenderer>().SetBlendShapeWeight(intData, floatData);
MirrorExtensions.UpdateMirror();
}
else
{
((Module)FusionModule.Instance).LoggerInstance.Error($"Failed to obtain Avatar for PlayerId {shortId}");
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
}
}
}
namespace AdvancedAvatarControl.BoneMenu
{
public class BoneMenu
{
public static SkinnedMeshRenderer SelectedMeshRenderer;
public static SkinnedMeshRenderer[] SkinnedMeshRenderers;
private static MenuCategory blendShapes;
private static MenuCategory meshRenderersMenu;
private static Dictionary<int, List<float>> initialBlendShapeWeights = new Dictionary<int, List<float>>();
public static void CreateBoneMenu()
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
MenuCategory obj = MenuManager.CreateCategory("Advanced Avatar Control", Color.cyan);
blendShapes = obj.CreateCategory("Blend Shapes", Color.green);
MenuCategory meshRenderersCategory = blendShapes.CreateCategory("Select Mesh Renderer", Color.green);
MenuCategory obj2 = obj.CreateCategory("Eye Movement", Color.green);
blendShapes.CreateFunctionElement("Refresh", Color.green, (Action)delegate
{
RefreshBlendShapes(blendShapes);
});
meshRenderersCategory.CreateFunctionElement("Refresh", Color.green, (Action)delegate
{
RefreshMeshRenderers(meshRenderersCategory);
});
obj2.CreateFloatElement("Movement Speed", Color.white, Prefs.EyeMovementSpeed.Value, 1f, 1f, 25f, (Action<float>)delegate(float value)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
if ((Object)(object)((Component)Player.playerHead).gameObject.GetComponent<PlayerEyeController>() != (Object)null)
{
Prefs.EyeMovementSpeed.Value = value;
}
else
{
Notifier.Send(new Notification
{
Title = NotificationText.op_Implicit("Opps!"),
ShowTitleOnPopup = true,
Message = NotificationText.op_Implicit("The player does not seem to have the PlayerEyeController component. Please add it first."),
Type = (NotificationType)1
});
}
});
}
public static void RefreshMeshRenderers(MenuCategory meshRenderersCategory)
{
//IL_0028: 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)
meshRenderersCategory.Elements.Clear();
meshRenderersCategory.CreateFunctionElement("Refresh", Color.green, (Action)delegate
{
RefreshMeshRenderers(meshRenderersCategory);
});
SkinnedMeshRenderers = Il2CppArrayBase<SkinnedMeshRenderer>.op_Implicit(((Component)Player.GetCurrentAvatar()).gameObject.GetComponentsInChildren<SkinnedMeshRenderer>());
SkinnedMeshRenderer[] skinnedMeshRenderers = SkinnedMeshRenderers;
foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers)
{
meshRenderersCategory.CreateFunctionElement(((Object)((Component)skinnedMeshRenderer).gameObject).name, Color.white, (Action)delegate
{
SelectedMeshRenderer = skinnedMeshRenderer;
if (!initialBlendShapeWeights.ContainsKey(((Object)((Component)skinnedMeshRenderer).gameObject).GetInstanceID()))
{
List<float> list = new List<float>();
for (int j = 0; j < skinnedMeshRenderer.sharedMesh.blendShapeCount; j++)
{
list.Add(skinnedMeshRenderer.GetBlendShapeWeight(j));
}
initialBlendShapeWeights[((Object)((Component)skinnedMeshRenderer).gameObject).GetInstanceID()] = list;
}
});
}
}
public static void RefreshBlendShapes(MenuCategory blendShapes)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0103: Unknown result type (might be due to invalid IL or missing references)
blendShapes.Elements.Clear();
MenuCategory meshRenderersCategory = blendShapes.CreateCategory("Select Mesh Renderer", Color.green);
meshRenderersCategory.CreateFunctionElement("Refresh", Color.green, (Action)delegate
{
RefreshMeshRenderers(meshRenderersCategory);
});
blendShapes.CreateFunctionElement("Refresh", Color.green, (Action)delegate
{
RefreshBlendShapes(blendShapes);
});
if (!((Object)(object)SelectedMeshRenderer != (Object)null) || !((Object)(object)SelectedMeshRenderer.sharedMesh != (Object)null))
{
return;
}
int blendShapeCount = SelectedMeshRenderer.sharedMesh.blendShapeCount;
foreach (int i in Enumerable.Range(0, blendShapeCount))
{
float blendShapeWeight = SelectedMeshRenderer.GetBlendShapeWeight(i);
string blendShapeName = SelectedMeshRenderer.sharedMesh.GetBlendShapeName(i);
blendShapes.CreateFloatElement(blendShapeName, Color.white, blendShapeWeight, 10f, 0f, 100f, (Action<float>)delegate(float value)
{
if (MelonMod.FusionInstalled && NetworkInfo.HasServer)
{
FusionModule.Instance.SendBlendBoneMessage(value, i);
}
else
{
SelectedMeshRenderer.SetBlendShapeWeight(i, value);
MirrorExtensions.UpdateMirror();
}
});
}
}
public static void OnSwitchAvatar(Avatar avatar)
{
if ((Object)(object)SelectedMeshRenderer != (Object)null && initialBlendShapeWeights.TryGetValue(((Object)((Component)SelectedMeshRenderer).gameObject).GetInstanceID(), out var value))
{
for (int i = 0; i < value.Count; i++)
{
SelectedMeshRenderer.SetBlendShapeWeight(i, value[i]);
}
}
}
}
}