Bonelab mods are targeting MelonLoader version 0.5.7. Newer versions will not work!, so double-check your MelonLoader version if you're having issues.
Decompiled source of AdvancedAvatarControl v1.1.1
Mods/AdvancedAvatarControl.dll
Decompiled 2 months agousing 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]); } } } } }