Decompiled source of MimesisSlotKeys v1.0.1

MimesisSlotKeys.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using MimesisSlotKeys;
using Mimic.Actors;
using Mimic.InputSystem;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(SlotKeysMod), "MimesisSlotKeys", "1.0.0", "vonhoon", null)]
[assembly: MelonGame(null, "MIMESIS")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MimesisSlotKeys")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MimesisSlotKeys")]
[assembly: AssemblyTitle("MimesisSlotKeys")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 MimesisSlotKeys
{
	public enum EmoteMode
	{
		Numpad,
		ShiftNumber,
		CtrlNumber
	}
	public class SlotKeysMod : MelonMod
	{
		internal static Instance Log;

		private static MelonPreferences_Category _cat;

		private static MelonPreferences_Entry<int> _emoteModeEntry;

		internal const int KeyCount = 4;

		internal const int EmoteCount = 10;

		private static InputManager _appliedInputman;

		private static EmoteMode _appliedMode;

		private static readonly string[] _modeLabels = new string[3] { "Numpad", "Shift + #", "Ctrl + #" };

		internal static EmoteMode Mode
		{
			get
			{
				int num = ((_emoteModeEntry != null) ? _emoteModeEntry.Value : 0);
				if (num < 0 || num > 2)
				{
					num = 0;
				}
				return (EmoteMode)num;
			}
			set
			{
				if (_emoteModeEntry != null)
				{
					_emoteModeEntry.Value = (int)value;
					MelonPreferences_Category cat = _cat;
					if (cat != null)
					{
						cat.SaveToFile(false);
					}
				}
				_appliedInputman = null;
			}
		}

		public override void OnInitializeMelon()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			Log = ((MelonBase)this).LoggerInstance;
			_cat = MelonPreferences.CreateCategory("MimesisSlotKeys");
			_emoteModeEntry = _cat.CreateEntry<int>("EmoteMode", 0, (string)null, "Emote binding: 0 = Numpad 1-4, 1 = Shift + top-row 1-4, 2 = Ctrl + top-row 1-4. Top-row 1-4 always selects inventory slots 1-4.", false, false, (ValueValidator)null, (string)null);
			Type typeFromHandle = typeof(ProtoActor);
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeFromHandle, "ProcessUISelectKey", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SlotKeysMod), "InventoryPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			((MelonBase)this).HarmonyInstance.Patch((MethodBase)AccessTools.Method(typeFromHandle, "ProcessEmoteKey", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SlotKeysMod), "EmotePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log.Msg($"Initialized. EmoteMode={Mode}. Top-row 1-4 = inventory slots.");
		}

		private static InputManager GetInputman()
		{
			if (!((Object)(object)Hub.s == (Object)null))
			{
				return Traverse.Create((object)Hub.s).Property("inputman", (object[])null).GetValue<InputManager>();
			}
			return null;
		}

		private static MMEmoteTable GetEmoteTable()
		{
			if ((Object)(object)Hub.s == (Object)null)
			{
				return null;
			}
			object value = Traverse.Create((object)Hub.s).Property("tableman", (object[])null).GetValue();
			if (value != null)
			{
				return Traverse.Create(value).Field("emote").GetValue<MMEmoteTable>();
			}
			return null;
		}

		private static void ShowEmoteBlockedToast()
		{
			try
			{
				object value = Traverse.Create(Traverse.Create((object)Hub.s).Property("tableman", (object[])null).GetValue()).Field("uiprefabs").GetValue();
				string value2 = Traverse.Create(typeof(Hub)).Method("GetL10NText", new object[1] { "STRING_DO_NOT_EMOTE" }).GetValue<string>();
				Traverse.Create(value).Method("ShowTimerDialog", new object[3] { "ToastSimple", 0f, value2 }).GetValue();
			}
			catch
			{
			}
		}

		private static bool ShiftHeld(Keyboard kb)
		{
			if (!((ButtonControl)kb.leftShiftKey).isPressed)
			{
				return ((ButtonControl)kb.rightShiftKey).isPressed;
			}
			return true;
		}

		private static bool CtrlHeld(Keyboard kb)
		{
			if (!((ButtonControl)kb.leftCtrlKey).isPressed)
			{
				return ((ButtonControl)kb.rightCtrlKey).isPressed;
			}
			return true;
		}

		private static bool EmoteModifierHeld(Keyboard kb)
		{
			return Mode switch
			{
				EmoteMode.ShiftNumber => ShiftHeld(kb), 
				EmoteMode.CtrlNumber => CtrlHeld(kb), 
				_ => false, 
			};
		}

		private static KeyControl Digit(Keyboard kb, int i)
		{
			return (KeyControl)(i switch
			{
				0 => kb.digit1Key, 
				1 => kb.digit2Key, 
				2 => kb.digit3Key, 
				_ => kb.digit4Key, 
			});
		}

		private static void EnsureEmoteBindings(InputManager im)
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)im == (Object)null || (Object)(object)im.data == (Object)null || im.data.data == null)
			{
				return;
			}
			EmoteMode mode = Mode;
			if (im == _appliedInputman && mode == _appliedMode)
			{
				return;
			}
			foreach (Mapping datum in im.data.data)
			{
				int num = EmoteActionIndex(datum.action);
				if (num < 1 || num > 10)
				{
					continue;
				}
				HashSet<string> hashSet = SplitKeys(datum.keys);
				string item = "k_num" + ((num != 10) ? num : 0);
				if (num <= 4)
				{
					hashSet.Clear();
					if (mode == EmoteMode.Numpad)
					{
						hashSet.Add(item);
					}
				}
				else
				{
					if (mode != EmoteMode.Numpad)
					{
						continue;
					}
					hashSet.Add(item);
				}
				datum.keys = string.Join(",", hashSet);
			}
			im.RefreshInputAssign();
			_appliedInputman = im;
			_appliedMode = mode;
			Instance log = Log;
			if (log != null)
			{
				log.Msg($"Applied emote bindings for mode {mode}.");
			}
		}

		private static HashSet<string> SplitKeys(string keys)
		{
			HashSet<string> hashSet = new HashSet<string>();
			if (string.IsNullOrEmpty(keys))
			{
				return hashSet;
			}
			string[] array = keys.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length > 0)
				{
					hashSet.Add(text);
				}
			}
			return hashSet;
		}

		private static int EmoteActionIndex(InputAction a)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Expected I4, but got Unknown
			int num = (int)a;
			if (num < 21 || num > 30)
			{
				return 0;
			}
			return num - 20;
		}

		private static void InventoryPostfix(ProtoActor __instance)
		{
			try
			{
				EnsureEmoteBindings(GetInputman());
				Keyboard current = Keyboard.current;
				if (current == null)
				{
					return;
				}
				bool flag = Mode != EmoteMode.Numpad;
				bool flag2 = flag && EmoteModifierHeld(current);
				for (int i = 0; i < 4; i++)
				{
					if (((ButtonControl)Digit(current, i)).wasPressedThisFrame && !(flag && flag2))
					{
						SelectInventorySlot(__instance, i);
					}
				}
			}
			catch (Exception ex)
			{
				Instance log = Log;
				if (log != null)
				{
					log.Error("InventoryPostfix: " + ex);
				}
			}
		}

		private static void EmotePostfix(ProtoActor __instance)
		{
			try
			{
				if (Mode == EmoteMode.Numpad)
				{
					return;
				}
				Keyboard current = Keyboard.current;
				if (current == null || !EmoteModifierHeld(current))
				{
					return;
				}
				for (int i = 0; i < 4; i++)
				{
					if (((ButtonControl)Digit(current, i)).wasPressedThisFrame)
					{
						TriggerEmote(__instance, i + 1);
						break;
					}
				}
			}
			catch (Exception ex)
			{
				Instance log = Log;
				if (log != null)
				{
					log.Error("EmotePostfix: " + ex);
				}
			}
		}

		private static void SelectInventorySlot(ProtoActor actor, int index)
		{
			Traverse val = Traverse.Create((object)actor);
			object value = val.Field("inventory").GetValue();
			if (value == null)
			{
				return;
			}
			Traverse val2 = Traverse.Create(value);
			int num = 0;
			Traverse val3 = val2.Field("slotSize");
			if (val3.FieldExists())
			{
				num = val3.GetValue<int>();
			}
			if (num <= 0 || index < num)
			{
				object value2 = val.Property("main", (object[])null).GetValue();
				if (value2 != null)
				{
					Traverse.Create(value2).Method("TryPerformInteractionEnd", Array.Empty<object>()).GetValue();
				}
				val2.Method("SelectSlot", new object[1] { index }).GetValue();
			}
		}

		private static void TriggerEmote(ProtoActor actor, int emoteNumber)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			Traverse val = Traverse.Create((object)actor);
			Traverse val2 = val.Field("movementInput");
			if (val2.FieldExists())
			{
				Vector2 value = val2.GetValue<Vector2>();
				if (((Vector2)(ref value)).sqrMagnitude > 0f)
				{
					return;
				}
			}
			EmotePlayer value2 = val.Field("emotePlayer").GetValue<EmotePlayer>();
			if (value2 == null)
			{
				return;
			}
			if (value2.IsEmoteDisabledByHandheldItem())
			{
				ShowEmoteBlockedToast();
				return;
			}
			MMEmoteTable emoteTable = GetEmoteTable();
			InputAction val3 = (InputAction)(20 + emoteNumber);
			Emote val4 = default(Emote);
			if ((Object)(object)emoteTable != (Object)null && emoteTable.TryGetEmote(val3, ref val4) && val4 != null)
			{
				value2.SendStartEmote(val4.emoteMasterID);
			}
		}

		public override void OnGUI()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: 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)
			Scene activeScene = SceneManager.GetActiveScene();
			if (!(((Scene)(ref activeScene)).name != "MainMenuScene"))
			{
				GUILayout.BeginArea(new Rect((float)Screen.width - 250f - 16f, (float)Screen.height - 84f - 56f, 250f, 84f), GUI.skin.box);
				GUILayout.Label("Emote keys  (top-row 1-4 = inventory)", Array.Empty<GUILayoutOption>());
				int mode = (int)Mode;
				int num = GUILayout.Toolbar(mode, _modeLabels, Array.Empty<GUILayoutOption>());
				if (num != mode)
				{
					Mode = (EmoteMode)num;
				}
				GUILayout.EndArea();
			}
		}
	}
}