Decompiled source of AdvancedAvatarControl v1.1.1

Mods/AdvancedAvatarControl.dll

Decompiled 2 months ago
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]);
				}
			}
		}
	}
}