The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of Emote Binding v1.1.0
EmoteBinding.dll
Decompiled 3 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using PEAKEmoteLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EmoteBinding")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+7fb484383c0f53ec7451de9d46dbccf039b6ed51")] [assembly: AssemblyProduct("EmoteBinding")] [assembly: AssemblyTitle("EmoteBinding")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace EmoteBinding { [BepInPlugin("com.atomic.emotebinding", "Emote Binding", "2.4.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static Plugin instance; public static Dictionary<string, ConfigEntry<KeyCode>> EmoteBindings = new Dictionary<string, ConfigEntry<KeyCode>>(); public static Dictionary<string, EmoteWheelData> EmoteData = new Dictionary<string, EmoteWheelData>(); private static Type emoteRegistryType; private static MethodInfo getEmotesMethod; private bool baseEmotesRegistered = false; private bool customEmotesRegistered = false; private static readonly MethodInfo playEmoteMethod = AccessTools.Method(typeof(CharacterAnimations), "PlayEmote", (Type[])null, (Type[])null); private static readonly KeyCode[] DefaultKeySequence; private void Awake() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown instance = this; if (Chainloader.PluginInfos.ContainsKey("com.github.WaporVave.PEAKEmoteLib")) { SetupEmoteRegistryReflection(); } else { customEmotesRegistered = true; } PatchEmoteWheel(); Harmony val = new Harmony("com.atomic.emotebinding"); val.PatchAll(Assembly.GetExecutingAssembly()); } private void PatchEmoteWheel() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown Type type = AccessTools.TypeByName("EmoteWheel"); if (type != null) { MethodInfo methodInfo = AccessTools.Method(type, "Awake", new Type[0], (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(type, "Start", new Type[0], (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(type, "OnEnable", new Type[0], (Type[])null); MethodInfo methodInfo4 = methodInfo ?? methodInfo2 ?? methodInfo3; if (methodInfo4 != null) { Harmony val = new Harmony("com.atomic.emotebinding"); val.Patch((MethodBase)methodInfo4, new HarmonyMethod(typeof(Plugin), "EmoteWheel_Init_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Successfully patched " + methodInfo4.Name + " for dynamic base emote discovery.")); } else { ((BaseUnityPlugin)this).Logger.LogError((object)"No Awake/Start/OnEnable found on EmoteWheel. Using fallback."); RegisterDefaultEmotesFallback(); } } else { ((BaseUnityPlugin)this).Logger.LogError((object)"Could not find type 'EmoteWheel'. Using fallback."); RegisterDefaultEmotesFallback(); } } private static void EmoteWheel_Init_Prefix(object __instance) { //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance == (Object)null || instance.baseEmotesRegistered) { return; } FieldInfo field = __instance.GetType().GetField("data", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { ((BaseUnityPlugin)instance).Logger.LogError((object)"EmoteWheel 'data' field not found."); instance.RegisterDefaultEmotesFallback(); return; } if (!(field.GetValue(__instance) is IList list)) { ((BaseUnityPlugin)instance).Logger.LogError((object)"EmoteWheel 'data' invalid or null."); instance.RegisterDefaultEmotesFallback(); return; } int num = 0; foreach (object item in list) { if (item == null) { continue; } Type type = item.GetType(); FieldInfo field2 = type.GetField("emoteName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field3 = type.GetField("anim", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); string text = field2?.GetValue(item) as string; string text2 = field3?.GetValue(item) as string; if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && !EmoteBindings.ContainsKey(text)) { KeyCode defaultKeycode = (KeyCode)0; if (num < DefaultKeySequence.Length) { defaultKeycode = DefaultKeySequence[num]; num++; } instance.RegisterBaseEmoteBinding("Base Game Emotes (Dynamic)", defaultKeycode, text, text2); } } instance.baseEmotesRegistered = true; } private void RegisterDefaultEmotesFallback() { if (!baseEmotesRegistered) { RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)53, "Thumbs Up", "A_Scout_Emote_ThumbsUp"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)54, "Think", "A_Scout_Emote_Think"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)55, "No-No", "A_Scout_Emote_Nono"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)56, "Play Dead", "A_Scout_Emote_Flex"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)57, "Shrug", "A_Scout_Emote_Shrug"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)48, "Crossed Arms", "A_Scout_Emote_CrossedArms"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)45, "Dance", "A_Scout_Emote_Dance1"); RegisterBaseEmoteBinding("Default Emotes (Fallback)", (KeyCode)61, "Salute", "A_Scout_Emote_Salute"); baseEmotesRegistered = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Dynamic discovery failed. Using hardcoded emote list."); } } private void RegisterBaseEmoteBinding(string section, KeyCode defaultKeycode, string emoteName, string animName) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) ConfigEntry<KeyCode> value = ((BaseUnityPlugin)this).Config.Bind<KeyCode>(section, emoteName, defaultKeycode, "Key binding for emote: " + emoteName); EmoteBindings[emoteName] = value; EmoteWheelData val = ScriptableObject.CreateInstance<EmoteWheelData>(); val.emoteName = emoteName; val.anim = animName; EmoteData[emoteName] = val; } private void SetupEmoteRegistryReflection() { try { Assembly assembly = Assembly.GetAssembly(typeof(Emote)); if (assembly == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"PEAKEmoteLib assembly could not be found."); return; } emoteRegistryType = assembly.GetType("PEAKEmoteLib.EmoteRegistry"); if (emoteRegistryType == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"PEAKEmoteLib.EmoteRegistry type not found via reflection."); return; } getEmotesMethod = AccessTools.Method(emoteRegistryType, "GetEmotes", (Type[])null, (Type[])null); if (getEmotesMethod == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"PEAKEmoteLib.EmoteRegistry.GetEmotes() method not found via reflection."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Error setting up EmoteRegistry reflection: " + ex.Message)); } } private void RegisterCustomEmotes() { if (getEmotesMethod == null || customEmotesRegistered) { return; } if (!(getEmotesMethod.Invoke(null, null) is IReadOnlyDictionary<string, Emote> readOnlyDictionary)) { if (customEmotesRegistered) { ((BaseUnityPlugin)this).Logger.LogError((object)"Failed to invoke EmoteRegistry.GetEmotes() via reflection."); } return; } int num = 0; foreach (KeyValuePair<string, Emote> item in readOnlyDictionary) { Emote value = item.Value; if (value != null) { string name = value.Name; string name2 = value.Name; if (!string.IsNullOrEmpty(name) && !EmoteBindings.ContainsKey(name)) { ConfigEntry<KeyCode> value2 = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Custom Emotes", name, (KeyCode)0, "Key binding for emote: " + name); EmoteBindings[name] = value2; EmoteWheelData val = ScriptableObject.CreateInstance<EmoteWheelData>(); val.emoteName = name; val.anim = name2; EmoteData[name] = val; num++; } } } if (num > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Registered {num} custom emotes into Config and EmoteWheel."); } if (readOnlyDictionary.Count > 0) { customEmotesRegistered = true; } } private void Update() { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Invalid comparison between Unknown and I4 //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (!customEmotesRegistered) { RegisterCustomEmotes(); } if ((Object)(object)Character.localCharacter == (Object)null || (Object)(object)Character.localCharacter.refs?.animations == (Object)null) { return; } foreach (KeyValuePair<string, ConfigEntry<KeyCode>> emoteBinding in EmoteBindings) { if ((int)emoteBinding.Value.Value != 0 && Input.GetKeyDown(emoteBinding.Value.Value) && EmoteData.TryGetValue(emoteBinding.Key, out EmoteWheelData value)) { TryPlayEmote(value.anim); } } } public static void TryPlayEmote(string emoteName) { if (!((Object)(object)Character.localCharacter?.refs?.animations == (Object)null)) { CharacterAnimations animations = Character.localCharacter.refs.animations; if (playEmoteMethod == null) { ((BaseUnityPlugin)instance).Logger.LogError((object)"Could not find PlayEmote method!"); return; } playEmoteMethod.Invoke(animations, new object[1] { emoteName }); } } static Plugin() { KeyCode[] array = new KeyCode[8]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); DefaultKeySequence = (KeyCode[])(object)array; } } }