Decompiled source of ExpressionControl v1.0.2

Mods/ExpressionControl.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using ExpressionControl;
using ExpressionControl.Messages;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.VRMK;
using LabFusion.Data;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Player;
using LabFusion.SDK.Modules;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "ExpressionControl", "1.0.2", "notnotnotswipez", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ExpressionControl")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+97900410cdaaf864e79b0f67f57d47d08b983fe8")]
[assembly: AssemblyProduct("ExpressionControl")]
[assembly: AssemblyTitle("ExpressionControl")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ExpressionControl
{
	[HarmonyPatch(typeof(ArtRig), "SetArtOutputAvatar")]
	public class AvatarPatches
	{
		public static void Postfix(ArtRig __instance, PhysicsRig inRig, Avatar avatar)
		{
			MelonCoroutines.Start(WaitForAvatar(((Rig)inRig).manager, avatar));
		}

		private static IEnumerator WaitForAvatar(RigManager instance, Avatar newAvatar)
		{
			for (int i = 0; i < 5; i++)
			{
				yield return null;
			}
			if (((Object)instance).GetInstanceID() == ((Object)Player.RigManager).GetInstanceID())
			{
				Core.ApplyBlendshapesToAvatar(newAvatar, Core.blendshapePairs);
				Core.Broadcast();
			}
		}
	}
	public class Core : MelonMod
	{
		public static string lastBlendshapeName;

		private static Page mainPage;

		private static bool deletionMode = false;

		public static Dictionary<string, bool> blendshapePairs = new Dictionary<string, bool>();

		public static Dictionary<int, Dictionary<string, bool>> rigmanagerBlendshapePairs = new Dictionary<int, Dictionary<string, bool>>();

		public static MelonPreferences_Category category;

		public static MelonPreferences_Entry<string> savedString;

		public override void OnInitializeMelon()
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			ModuleManager.RegisterModule<ExpressionControlModule>();
			category = MelonPreferences.CreateCategory("ExpressionControl");
			savedString = category.CreateEntry<string>("SavedString", "", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			blendshapePairs = GetDictionaryFromString(savedString.Value);
			mainPage = Page.Root.CreatePage("Expression Control", Color.yellow, 0, true);
			RemakeMenu();
		}

		private void RemakeMenu()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			mainPage.RemoveAll();
			mainPage.CreateString("Blendshape Name", Color.white, "", (Action<string>)delegate(string str)
			{
				lastBlendshapeName = str;
			});
			mainPage.CreateFunction("+", Color.green, (Action)delegate
			{
				blendshapePairs.Add(lastBlendshapeName, value: false);
				RemakeMenu();
			});
			mainPage.CreateBool("Deletion Mode", Color.red, deletionMode, (Action<bool>)delegate(bool b)
			{
				deletionMode = b;
			});
			foreach (KeyValuePair<string, bool> keyPair in blendshapePairs)
			{
				mainPage.CreateBool(keyPair.Key, Color.white, keyPair.Value, (Action<bool>)delegate(bool b)
				{
					if (deletionMode)
					{
						blendshapePairs[keyPair.Key] = false;
						ApplyBlendshapesToLocalPlayer();
						blendshapePairs.Remove(keyPair.Key);
						RemakeMenu();
						SaveDictToFile();
						Broadcast();
					}
					else
					{
						blendshapePairs[keyPair.Key] = b;
						ApplyBlendshapesToLocalPlayer();
						SaveDictToFile();
						Broadcast();
					}
				});
			}
			mainPage.Remove((Element[])(object)new Element[0]);
		}

		public static void Broadcast()
		{
			if (!NetworkInfo.HasServer)
			{
				return;
			}
			ExpressionMessageData expressionMessageData = ExpressionMessageData.Create(blendshapePairs);
			FusionWriter val = FusionWriter.Create();
			try
			{
				ExpressionMessageData expressionMessageData2 = expressionMessageData;
				val.Write<ExpressionMessageData>(expressionMessageData2);
				FusionMessage val2 = FusionMessage.ModuleCreate<ExpressionMessage>(val);
				try
				{
					MessageSender.SendToServer((NetworkChannel)0, val2);
				}
				finally
				{
					((IDisposable)val2)?.Dispose();
				}
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}

		private void SaveDictToFile()
		{
			savedString.Value = GetStringFromDictionary(blendshapePairs);
			category.SaveToFile(false);
		}

		public static string GetStringFromDictionary(Dictionary<string, bool> keyValuePairs)
		{
			string text = keyValuePairs.Count + ";";
			foreach (KeyValuePair<string, bool> keyValuePair in keyValuePairs)
			{
				text = text + keyValuePair.Key + ";";
				text = text + keyValuePair.Value + ";";
			}
			return text;
		}

		public static Dictionary<string, bool> GetDictionaryFromString(string targetString)
		{
			if (targetString == "")
			{
				return new Dictionary<string, bool>();
			}
			string[] array = targetString.Split(";");
			int num = int.Parse(array[0]);
			Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
			for (int i = 1; i < num * 2; i += 2)
			{
				dictionary.Add(array[i], bool.Parse(array[i + 1]));
			}
			return dictionary;
		}

		private void ApplyBlendshapesToLocalPlayer()
		{
			ApplyBlendshapesToRigmanager(Player.RigManager, blendshapePairs);
		}

		public static void ApplyBlendshapesToRigmanager(RigManager rigManager, Dictionary<string, bool> blendshapePairs)
		{
			if (rigmanagerBlendshapePairs.ContainsKey(((Object)rigManager).GetInstanceID()))
			{
				rigmanagerBlendshapePairs[((Object)rigManager).GetInstanceID()] = blendshapePairs;
			}
			else
			{
				rigmanagerBlendshapePairs.Add(((Object)rigManager).GetInstanceID(), blendshapePairs);
			}
			ApplyBlendshapesToAvatar(rigManager.avatar, blendshapePairs);
			MirrorPatches.skinnedMeshRendererPairs.Clear();
		}

		public static Dictionary<string, bool> TryGetBlendShapePairFromRigmanager(RigManager rigManager)
		{
			if (rigmanagerBlendshapePairs.ContainsKey(((Object)rigManager).GetInstanceID()))
			{
				return rigmanagerBlendshapePairs[((Object)rigManager).GetInstanceID()];
			}
			return null;
		}

		public static void ApplyBlendshapesToAvatar(Avatar avatar, Dictionary<string, bool> blendshapePairs)
		{
			ApplyBlendshapesToSkinnedMeshRenderers(((Component)avatar).GetComponentsInChildren<SkinnedMeshRenderer>(), blendshapePairs);
		}

		public static void ApplyBlendshapesToSkinnedMeshRenderers(Il2CppArrayBase<SkinnedMeshRenderer> skinnedMeshRenderers, Dictionary<string, bool> blendshapePairs)
		{
			foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers)
			{
				foreach (KeyValuePair<string, bool> blendshapePair in blendshapePairs)
				{
					int blendShapeIndex = skinnedMeshRenderer.sharedMesh.GetBlendShapeIndex(blendshapePair.Key);
					if (blendShapeIndex != -1)
					{
						float num = (blendshapePair.Value ? 100f : 0f);
						skinnedMeshRenderer.SetBlendShapeWeight(blendShapeIndex, num);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Mirror), "LateUpdate")]
	public class MirrorPatches
	{
		public static Dictionary<int, Il2CppArrayBase<SkinnedMeshRenderer>> skinnedMeshRendererPairs = new Dictionary<int, Il2CppArrayBase<SkinnedMeshRenderer>>();

		public static void Prefix(Mirror __instance)
		{
			if (!Object.op_Implicit((Object)(object)__instance.Reflection) || skinnedMeshRendererPairs.ContainsKey(((Object)__instance.Reflection).GetInstanceID()))
			{
				return;
			}
			skinnedMeshRendererPairs.Add(((Object)__instance.Reflection).GetInstanceID(), ((Component)__instance.Reflection).GetComponentsInChildren<SkinnedMeshRenderer>());
			Il2CppArrayBase<SkinnedMeshRenderer> skinnedMeshRenderers = skinnedMeshRendererPairs[((Object)__instance.Reflection).GetInstanceID()];
			RigManager rigManager = __instance.rigManager;
			if (Object.op_Implicit((Object)(object)rigManager))
			{
				Dictionary<string, bool> dictionary = Core.TryGetBlendShapePairFromRigmanager(rigManager);
				if (dictionary != null)
				{
					Core.ApplyBlendshapesToSkinnedMeshRenderers(skinnedMeshRenderers, dictionary);
				}
			}
		}
	}
	public class ExpressionControlModule : Module
	{
		public override string Name => "ExpressionControl";

		public override string Author => "notnotnotswipez";

		public override Version Version => new Version(1, 0, 2);

		public override ConsoleColor Color => ConsoleColor.Yellow;

		protected override void OnModuleRegistered()
		{
			ModuleMessageHandler.RegisterHandler<ExpressionMessage>();
		}

		protected override void OnModuleUnregistered()
		{
		}
	}
}
namespace ExpressionControl.Messages
{
	public class ExpressionMessageData : IFusionSerializable
	{
		public PlayerId playerId;

		public string dictString;

		public void Deserialize(FusionReader reader)
		{
			playerId = PlayerIdManager.GetPlayerId(reader.ReadByte());
			dictString = reader.ReadString();
		}

		public void Serialize(FusionWriter writer)
		{
			writer.Write(playerId.SmallId);
			writer.Write(dictString);
		}

		public static ExpressionMessageData Create(Dictionary<string, bool> dict)
		{
			return new ExpressionMessageData
			{
				playerId = PlayerIdManager.LocalId,
				dictString = Core.GetStringFromDictionary(dict)
			};
		}
	}
	public class ExpressionMessage : ModuleMessageHandler
	{
		public override void HandleMessage(byte[] bytes, bool isServerHandled = false)
		{
			FusionReader val = FusionReader.Create(bytes);
			try
			{
				ExpressionMessageData expressionMessageData = val.ReadFusionSerializable<ExpressionMessageData>();
				if (NetworkInfo.IsServer && isServerHandled)
				{
					FusionMessage val2 = FusionMessage.ModuleCreate<ExpressionMessage>(bytes);
					try
					{
						MessageSender.BroadcastMessageExcept(PlayerId.op_Implicit(expressionMessageData.playerId), (NetworkChannel)0, val2, true);
					}
					finally
					{
						((IDisposable)val2)?.Dispose();
					}
				}
				NetworkPlayer val3 = default(NetworkPlayer);
				if (!expressionMessageData.playerId.IsMe && NetworkPlayerManager.TryGetPlayer(PlayerId.op_Implicit(expressionMessageData.playerId), ref val3))
				{
					Dictionary<string, bool> dictionaryFromString = Core.GetDictionaryFromString(expressionMessageData.dictString);
					if (dictionaryFromString != null)
					{
						Core.ApplyBlendshapesToRigmanager(val3.RigRefs.RigManager, dictionaryFromString);
					}
				}
			}
			finally
			{
				((IDisposable)val)?.Dispose();
			}
		}
	}
}