using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using Microsoft.CodeAnalysis; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("InfiniteEmote")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Adjusts CheckConditionsForEmote conditions")] [assembly: AssemblyFileVersion("1.3.3.0")] [assembly: AssemblyInformationalVersion("1.3.3+5772b8680c25c78aa9b8ebb313ada9a0f346c305")] [assembly: AssemblyProduct("InfiniteEmote")] [assembly: AssemblyTitle("InfiniteEmote")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.3.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 InfiniteEmote { [Serializable] public class Config : SyncedInstance { public bool WhileJumping = true; public bool WhileWalking = true; public bool WhileSprinting = true; public bool WhileCrouching; public bool WhileLadder; public bool WhileGrabbing; public bool WhileTyping; public bool WhileTerminal; public bool WhileHolding = true; public bool WhileHoldingTwoHand = true; [NonSerialized] private static string Section = "Emote while"; public Config(ConfigFile configFile) { InitInstance(this); Plugin.Debug("Loading emote while options"); WhileJumping = configFile.Bind(Section, "Jumping", WhileJumping, "Whether or not to allow emoting while Jumping").Value; WhileWalking = configFile.Bind(Section, "Walking", WhileWalking, "Whether or not to allow emoting while Walking").Value; WhileSprinting = configFile.Bind(Section, "Sprinting", WhileSprinting, "Whether or not to allow emoting while Sprinting").Value; WhileCrouching = configFile.Bind(Section, "Crouching", WhileCrouching, "Whether or not to allow emoting while Crouching").Value; WhileLadder = configFile.Bind(Section, "Ladder", WhileLadder, "Whether or not to allow emoting while climbing Ladder").Value; WhileGrabbing = configFile.Bind(Section, "Grabbing", WhileGrabbing, "Whether or not to allow emoting while Grabbing").Value; WhileTyping = configFile.Bind(Section, "Typing", WhileTyping, "Whether or not to allow emoting while Typing").Value; WhileTerminal = configFile.Bind(Section, "Terminal", WhileTerminal, "Whether or not to allow emoting while in the Terminal").Value; WhileHolding = configFile.Bind(Section, "Holding", WhileHolding, "Whether or not to allow emoting while Holding an object").Value; WhileHoldingTwoHand = configFile.Bind(Section, "HoldingTwoHand", WhileHoldingTwoHand, "Whether or not to allow emoting while Holding a two handed object").Value; } public void DebugValues() { Plugin.Debug($"WhileJumping '{WhileJumping}'"); Plugin.Debug($"WhileWalking '{WhileWalking}'"); Plugin.Debug($"WhileSprinting '{WhileSprinting}'"); Plugin.Debug($"WhileCrouching '{WhileCrouching}'"); Plugin.Debug($"WhileLadder '{WhileLadder}'"); Plugin.Debug($"WhileGrabbing '{WhileGrabbing}'"); Plugin.Debug($"WhileTyping '{WhileTyping}'"); Plugin.Debug($"WhileTerminal '{WhileTerminal}'"); Plugin.Debug($"WhileHoldingTwoHand '{WhileHoldingTwoHand}'"); } public static void RequestSync() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance.IsClient) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(SyncedInstance.IntSize, (Allocator)2, -1); try { SyncedInstance.MessageManager.SendNamedMessage("ModName_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_0047: 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_0068: Unknown result type (might be due to invalid IL or missing references) if (!SyncedInstance.IsHost) { return; } Plugin.Logger.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] array = SyncedInstance.SerializeToBytes(SyncedInstance.Instance); int num = array.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + SyncedInstance.IntSize, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(array, -1, 0); SyncedInstance.MessageManager.SendNamedMessage("ModName_OnReceiveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { Plugin.Logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (!((FastBufferReader)(ref reader)).TryBeginRead(SyncedInstance.IntSize)) { Plugin.Logger.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { Plugin.Logger.LogError((object)"Config sync error: Host could not sync."); return; } byte[] data = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref data, num, 0); SyncedInstance.SyncInstance(data); Plugin.Logger.LogInfo((object)"Successfully synced config with host."); } } internal class Keybinds : LcInputActions { public InputAction StopEmote => ((LcInputActions)this).Asset["StopEmote"]; public override void CreateInputActions(in InputActionMapBuilder builder) { ((LcInputActions)this).CreateInputActions(ref builder); builder.NewActionBinding().WithActionId("StopEmote").WithActionType((InputActionType)1) .WithKbmPath(Patches.stopEmoteKey) .WithGamepadPath(Patches.stopEmoteController) .WithBindingName("Stop Emote") .Finish(); } } internal class Patches { [CompilerGenerated] private static class <>O { public static Action <0>__onStopEmoteKey; public static HandleNamedMessageDelegate <1>__OnRequestSync; public static HandleNamedMessageDelegate <2>__OnReceiveSync; } public static Keybinds keybinds; public static string stopEmoteKey; public static string stopEmoteController; public static bool moreEmotes; private static PlayerControllerB localPlayerController { get { StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance != (Object)null)) { return null; } return instance.localPlayerController; } } [HarmonyPatch(typeof(PlayerControllerB), "Start")] [HarmonyPostfix] private static void StartPostfix(PlayerControllerB __instance) { Plugin.Debug("PlayerControllerB.StartPostfix"); keybinds.StopEmote.performed += onStopEmoteKey; keybinds.StopEmote.Enable(); } [HarmonyPatch(typeof(PlayerControllerB), "OnDisable")] [HarmonyPostfix] public static void OnDisablePostfix(PlayerControllerB __instance) { Plugin.Debug("OnDisablePostfix"); if ((Object)(object)__instance == (Object)(object)localPlayerController) { Plugin.Debug("localPlayerController is instance"); keybinds.StopEmote.performed -= onStopEmoteKey; keybinds.StopEmote.Disable(); } } private static void onStopEmoteKey(CallbackContext context) { Plugin.Debug("onStopEmoteKey"); if (localPlayerController.isPlayerControlled && ((NetworkBehaviour)localPlayerController).IsOwner) { Plugin.Debug("isPlayerControlled and IsOwner"); localPlayerController.performingEmote = false; localPlayerController.StopPerformingEmoteServerRpc(); localPlayerController.timeSinceStartingEmote = 0f; } } [HarmonyPatch(typeof(PlayerControllerB), "CheckConditionsForEmote")] [HarmonyPostfix] [HarmonyAfter(new string[] { "BetterEmotes", "MoreEmotes" })] private static void CheckConditionsForEmotePatch(PlayerControllerB __instance, ref bool __result) { if ((Object)(object)__instance == (Object)null) { return; } if (__instance.inSpecialInteractAnimation || __instance.isPlayerDead) { Plugin.Debug($"inSpecialInteractAnimation ({__instance.inSpecialInteractAnimation}) or isPlayerDead ({__instance.isPlayerDead})"); __result = false; return; } if (__instance.isGrabbingObjectAnimation) { Plugin.Debug($"isGrabbingObjectAnimation ({__instance.isGrabbingObjectAnimation}), whileGrabbing ({SyncedInstance.Instance.WhileGrabbing})"); if (!SyncedInstance.Instance.WhileGrabbing) { __result = false; return; } __result = true; } if (__instance.isHoldingObject) { Plugin.Debug($"isHoldingObject ({__instance.isHoldingObject}), whileHolding ({SyncedInstance.Instance.WhileHolding})"); if (!SyncedInstance.Instance.WhileHolding) { __result = false; return; } if (__instance.twoHanded) { Plugin.Debug($"twoHanded ({__instance.twoHanded}), whileHoldingTwoHand ({SyncedInstance.Instance.WhileHoldingTwoHand})"); if (!SyncedInstance.Instance.WhileHoldingTwoHand) { __result = false; return; } __result = true; } else { __result = true; } } if (__instance.isJumping) { Plugin.Debug($"isJumping, whileJumping ({SyncedInstance.Instance.WhileJumping})"); __result = SyncedInstance.Instance.WhileJumping; } if (__instance.isWalking) { Plugin.Debug($"isWalking, whileWalking ({SyncedInstance.Instance.WhileWalking})"); __result = SyncedInstance.Instance.WhileWalking; } if (__instance.isSprinting) { Plugin.Debug($"isSprinting, whileSprinting ({SyncedInstance.Instance.WhileSprinting})"); __result = SyncedInstance.Instance.WhileSprinting; } if (__instance.isCrouching) { Plugin.Debug($"isCrouching, whileCrouching ({SyncedInstance.Instance.WhileCrouching})"); __result = SyncedInstance.Instance.WhileCrouching; } if (__instance.isClimbingLadder) { Plugin.Debug($"isClimbingLadder, whileLadder ({SyncedInstance.Instance.WhileLadder})"); __result = SyncedInstance.Instance.WhileLadder; } if (__instance.isTypingChat) { int integer = __instance.playerBodyAnimator.GetInteger("emoteNumber"); Plugin.Debug($"isTypingChat, whileTyping ({SyncedInstance.Instance.WhileTyping}), moreEmotes ({moreEmotes}), currentEmote ({integer})"); if (moreEmotes && integer == 10) { Plugin.Debug("isEmoteNumber 10 (Sign for MoreEmotes)"); __result = true; } else { __result = SyncedInstance.Instance.WhileTyping; } } if (__instance.inTerminalMenu) { Plugin.Debug($"inTerminalMenu, whileTerminal ({SyncedInstance.Instance.WhileTerminal})"); __result = SyncedInstance.Instance.WhileTerminal; } if (!__result) { Plugin.Debug("__result false, following values"); Plugin.Debug($"!__instance.inSpecialInteractAnimation ({!__instance.inSpecialInteractAnimation})"); Plugin.Debug($"!__instance.isPlayerDead ({!__instance.isPlayerDead})"); Plugin.Debug($"!__instance.isJumping ({!__instance.isJumping})"); Plugin.Debug($"!__instance.isWalking ({!__instance.isWalking})"); Plugin.Debug($"!__instance.isCrouching ({!__instance.isCrouching})"); Plugin.Debug($"!__instance.isClimbingLadder ({!__instance.isClimbingLadder})"); Plugin.Debug($"!__instance.isGrabbingObjectAnimation ({!__instance.isGrabbingObjectAnimation})"); Plugin.Debug($"!__instance.inTerminalMenu ({!__instance.inTerminalMenu})"); Plugin.Debug($"!__instance.isTypingChat ({!__instance.isTypingChat})"); bool flag = !__instance.inSpecialInteractAnimation && !__instance.isPlayerDead && !__instance.isJumping && !__instance.isWalking && !__instance.isCrouching && !__instance.isClimbingLadder && !__instance.isGrabbingObjectAnimation && !__instance.inTerminalMenu && !__instance.isTypingChat; Plugin.Debug($"result ({flag})"); __result = flag; } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void InitializeLocalPlayer() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown Plugin.Debug("InitializeLocalPlayer()"); if (SyncedInstance.IsHost) { try { CustomMessagingManager messageManager = SyncedInstance.MessageManager; object obj = <>O.<1>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = Config.OnRequestSync; <>O.<1>__OnRequestSync = val; obj = (object)val; } messageManager.RegisterNamedMessageHandler("ModName_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); SyncedInstance.Synced = true; return; } catch (Exception ex) { Plugin.Logger.LogError((object)ex); return; } } SyncedInstance.Synced = false; CustomMessagingManager messageManager2 = SyncedInstance.MessageManager; object obj2 = <>O.<2>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = Config.OnReceiveSync; <>O.<2>__OnReceiveSync = val2; obj2 = (object)val2; } messageManager2.RegisterNamedMessageHandler("ModName_OnReceiveConfigSync", (HandleNamedMessageDelegate)obj2); Config.RequestSync(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "StartDisconnect")] public static void PlayerLeave() { Plugin.Debug("PlayerLeave()"); SyncedInstance.RevertSync(); } } [BepInPlugin("InfiniteEmote", "InfiniteEmote", "1.3.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public static Texture2D texture; public static bool debug; public static ManualLogSource Logger; private void Awake() { //IL_0147: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; Logger.LogInfo((object)"Plugin InfiniteEmote loading..."); debug = ((BaseUnityPlugin)this).Config.Bind("Dev", "Debug", false, "Whether or not to enable debug logging and debug helpers").Value; Logger.LogInfo((object)$"Debug enabled: {debug}"); new Config(((BaseUnityPlugin)this).Config); Debug("Loading keybind defaults"); ConfigEntry val = ((BaseUnityPlugin)this).Config.Bind("Keys", "Stop Emote Key", "/minus", "Default keybind to stop emoting"); Patches.stopEmoteKey = validatePrefixes(new string[2] { "", "" }, "", val.Value); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind("Keys", "Stop Emote Button", "/leftStickPress", "Default controller button to stop emoting"); Patches.stopEmoteController = validatePrefixes(new string[1] { "" }, "", val2.Value); Debug("Loaded key '" + Patches.stopEmoteKey + "'"); Debug("Loaded button '" + Patches.stopEmoteController + "'"); checkForMods(); Patches.keybinds = new Keybinds(); new Harmony("InfiniteEmote").PatchAll(typeof(Patches)); Logger.LogInfo((object)"Plugin InfiniteEmote is loaded!"); } public static string validatePrefixes(string[] prefixes, string defaultPrefix, string value) { if (value.Equals("")) { return ""; } foreach (string text in prefixes) { if (value.ToLower().StartsWith(text.ToLower())) { return value; } } return defaultPrefix + "/" + value; } public static void Debug(string message) { if (debug) { Logger.LogDebug((object)message); } } public static void checkForMods() { Debug("checkForMods"); foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; if (metadata.GUID.Equals("MoreEmotes") || metadata.GUID.Equals("BetterEmotes")) { Debug("Found MoreEmotes/BetterEmotes"); Patches.moreEmotes = true; break; } } } } [Serializable] public class SyncedInstance { [NonSerialized] protected static int IntSize = 4; internal static CustomMessagingManager MessageManager => NetworkManager.Singleton.CustomMessagingManager; internal static bool IsClient => NetworkManager.Singleton.IsClient; internal static bool IsHost => NetworkManager.Singleton.IsHost; public static T Default { get; private set; } public static T Instance { get; private set; } public static bool Synced { get; internal set; } protected void InitInstance(T instance) { Default = instance; Instance = instance; IntSize = 4; } internal static void SyncInstance(byte[] data) { Instance = DeserializeFromBytes(data); Synced = true; } internal static void RevertSync() { Instance = Default; Synced = false; } public static byte[] SerializeToBytes(T val) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream memoryStream = new MemoryStream(); try { binaryFormatter.Serialize(memoryStream, val); return memoryStream.ToArray(); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error serializing instance: {arg}"); return null; } } public static T DeserializeFromBytes(byte[] data) { BinaryFormatter binaryFormatter = new BinaryFormatter(); using MemoryStream serializationStream = new MemoryStream(data); try { return (T)binaryFormatter.Deserialize(serializationStream); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error deserializing instance: {arg}"); return default(T); } } } public static class PluginInfo { public const string PLUGIN_GUID = "InfiniteEmote"; public const string PLUGIN_NAME = "InfiniteEmote"; public const string PLUGIN_VERSION = "1.3.3"; } }