Decompiled source of KeyBindManager v0.1.0

KeyBindManager.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Logging;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("KeyBindManager")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DiscoveryPins")]
[assembly: AssemblyCopyright("Copyright ©  2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("08a6f7d7-cf93-4931-aecd-abf2ce6ed34c")]
[assembly: AssemblyFileVersion("0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[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 Logging
{
	internal static class Log
	{
		internal enum InfoLevel
		{
			Low,
			Medium,
			High
		}

		private static ManualLogSource logSource;

		internal static ConfigEntry<InfoLevel> Verbosity { get; set; }

		internal static InfoLevel VerbosityLevel => Verbosity.Value;

		internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low;

		internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium;

		internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High;

		internal static void Init(ManualLogSource logSource)
		{
			Log.logSource = logSource;
		}

		internal static void LogDebug(object data)
		{
			logSource.LogDebug(data);
		}

		internal static void LogError(object data)
		{
			logSource.LogError(data);
		}

		internal static void LogFatal(object data)
		{
			logSource.LogFatal(data);
		}

		internal static void LogMessage(object data)
		{
			logSource.LogMessage(data);
		}

		internal static void LogWarning(object data)
		{
			logSource.LogWarning(data);
		}

		internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low)
		{
			if (Verbosity == null || VerbosityLevel >= level)
			{
				logSource.LogInfo(data);
			}
		}

		internal static void LogGameObject(GameObject prefab, bool includeChildren = false)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			LogInfo("***** " + ((Object)prefab).name + " *****");
			Component[] components = prefab.GetComponents<Component>();
			for (int i = 0; i < components.Length; i++)
			{
				LogComponent(components[i]);
			}
			if (!includeChildren)
			{
				return;
			}
			LogInfo("***** " + ((Object)prefab).name + " (children) *****");
			foreach (Transform item in prefab.transform)
			{
				Transform val = item;
				if (Object.op_Implicit((Object)(object)val))
				{
					LogInfo(" - " + ((Object)val).name);
					components = ((Component)val).GetComponents<Component>();
					for (int i = 0; i < components.Length; i++)
					{
						LogComponent(components[i]);
					}
				}
			}
		}

		internal static void LogComponent(Component compo)
		{
			if (!Object.op_Implicit((Object)(object)compo))
			{
				return;
			}
			try
			{
				LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---");
			}
			catch (Exception ex)
			{
				LogError(ex.ToString());
				LogWarning("Could not get type name for component!");
				return;
			}
			try
			{
				foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}");
					}
					catch (Exception ex2)
					{
						LogError(ex2.ToString());
						LogWarning("Could not get property: " + declaredProperty.Name + " for component!");
					}
				}
			}
			catch (Exception ex3)
			{
				LogError(ex3.ToString());
				LogWarning("Could not get properties for component!");
			}
			try
			{
				foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType()))
				{
					try
					{
						LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}");
					}
					catch (Exception ex4)
					{
						LogError(ex4.ToString());
						LogWarning("Could not get field: " + declaredField.Name + " for component!");
					}
				}
			}
			catch (Exception ex5)
			{
				LogError(ex5.ToString());
				LogWarning("Could not get fields for component!");
			}
		}
	}
}
namespace KeyBindManager
{
	[BepInPlugin("Searica.Valheim.KeyBindManager", "KeyBindManager", "0.1.0")]
	[BepInDependency("com.jotunn.jotunn", "2.30.1")]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal sealed class KeyBindManager : BaseUnityPlugin
	{
		internal sealed class ConfigHandlerDB
		{
			private readonly string PluginGuid;

			private readonly ConfigDefinition ConfigDef;

			private readonly ConfigEntryBase OriginalConfigEntry;

			private ConfigEntry<string> StringHandler;

			private ConfigEntry<KeyCode> KeyCodeHandler;

			private ConfigEntry<KeyboardShortcut> ShortcutHandler;

			private ConfigEntry<string> StringOriginal;

			private ConfigEntry<KeyCode> KeyCodeOriginal;

			private ConfigEntry<KeyboardShortcut> ShortcutOriginal;

			private readonly Type ConfigType;

			private bool PauseUpdateEvents;

			public ConfigHandlerDB(string pluginGuid, ConfigEntryBase configEntry, Type type)
			{
				PluginGuid = pluginGuid;
				ConfigDef = configEntry.Definition;
				OriginalConfigEntry = configEntry;
				ConfigType = type;
				try
				{
					if (type == typeof(KeyCode))
					{
						KeyCodeOriginal = (ConfigEntry<KeyCode>)(object)configEntry;
						KeyCodeHandler = BindHandlerConfig<KeyCode>(pluginGuid, ConfigDef, KeyCodeOriginal);
					}
					else if (type == typeof(KeyboardShortcut))
					{
						ShortcutOriginal = (ConfigEntry<KeyboardShortcut>)(object)configEntry;
						ShortcutHandler = BindHandlerConfig<KeyboardShortcut>(pluginGuid, ConfigDef, ShortcutOriginal);
					}
					else if (type == typeof(string))
					{
						StringOriginal = (ConfigEntry<string>)(object)configEntry;
						StringHandler = BindHandlerConfig<string>(pluginGuid, ConfigDef, StringOriginal);
					}
					else
					{
						Log.LogWarning("Invalid type for config handler! " + type.ToString());
					}
				}
				catch (Exception ex)
				{
					Log.LogError(ex.Message ?? "");
					Log.LogWarning("Failed to create handler config entry for " + pluginGuid + " - " + configEntry.Definition.Key);
				}
			}

			private ConfigEntry<T> BindHandlerConfig<T>(string pluginGuid, ConfigDefinition originalDefinition, ConfigEntry<T> originalEntry)
			{
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Expected O, but got Unknown
				ConfigEntry<T> val = ((BaseUnityPlugin)Instance).Config.Bind<T>(pluginGuid, originalDefinition.Key, (T)((ConfigEntryBase)originalEntry).DefaultValue, new ConfigDescription(((ConfigEntryBase)originalEntry).Description.Description, ((ConfigEntryBase)originalEntry).Description.AcceptableValues, ((ConfigEntryBase)originalEntry).Description.Tags));
				originalEntry.Value = val.Value;
				originalEntry.SettingChanged += OriginalConfigChanged;
				val.SettingChanged += HandlerConfigChanged;
				return val;
			}

			public void HandlerConfigChanged(object obj, EventArgs args)
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				if (!PauseUpdateEvents)
				{
					Log.LogInfo("Handler setting changed", Log.InfoLevel.Medium);
					PauseUpdateEvents = true;
					if (ConfigType == typeof(string))
					{
						StringOriginal.Value = StringHandler.Value;
					}
					else if (ConfigType == typeof(KeyCode))
					{
						KeyCodeOriginal.Value = KeyCodeHandler.Value;
					}
					else if (ConfigType == typeof(KeyboardShortcut))
					{
						ShortcutOriginal.Value = ShortcutHandler.Value;
					}
					PauseUpdateEvents = false;
				}
			}

			public void OriginalConfigChanged(object obj, EventArgs args)
			{
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				if (!PauseUpdateEvents)
				{
					Log.LogInfo("Original setting changed", Log.InfoLevel.Medium);
					PauseUpdateEvents = true;
					if (ConfigType == typeof(string))
					{
						StringHandler.Value = StringOriginal.Value;
					}
					else if (ConfigType == typeof(KeyCode))
					{
						KeyCodeHandler.Value = KeyCodeOriginal.Value;
					}
					else if (ConfigType == typeof(KeyboardShortcut))
					{
						ShortcutHandler.Value = ShortcutOriginal.Value;
					}
					PauseUpdateEvents = false;
				}
			}
		}

		public const string PluginName = "KeyBindManager";

		internal const string Author = "Searica";

		public const string PluginGUID = "Searica.Valheim.KeyBindManager";

		public const string PluginVersion = "0.1.0";

		internal static MethodInfo ConfigGetterInfo = AccessTools.PropertyGetter(typeof(BaseUnityPlugin), "Config");

		internal static readonly List<string> KeyBindDescHints = new List<string> { "key bind", "shortcut", "key" };

		internal static HashSet<ConfigDefinition> IgnoreConfigList = new HashSet<ConfigDefinition>();

		internal static KeyBindManager Instance;

		internal static ConfigFileWatcher ConfigFileWatcher;

		internal static Dictionary<string, ConfigFile> PluginConfigsMap = new Dictionary<string, ConfigFile>();

		internal static Dictionary<string, Dictionary<ConfigDefinition, ConfigHandlerDB>> ConfigHandlers = new Dictionary<string, Dictionary<ConfigDefinition, ConfigHandlerDB>>();

		internal const string GlobalSection = "Global";

		internal static bool PauseUpdateEvents = false;

		public void Awake()
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			Log.Verbosity = ConfigFileExtensions.BindConfigInOrder<Log.InfoLevel>(((BaseUnityPlugin)this).Config, "Logging", "Verbosity", Log.InfoLevel.Low, "Low will log basic information about the mod. Medium will log information that is useful for troubleshooting. High will log a lot of information, do not set it to this without good reason as it will slow down your game.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.KeyBindManager");
			Game.isModded = true;
			ConfigFileWatcher.OnConfigFileReloaded += delegate
			{
				UpdatePlugin(saveConfig: false);
			};
			SynchronizationManager.OnConfigurationWindowClosed += delegate
			{
				UpdatePlugin();
			};
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				UpdatePlugin();
			};
		}

		internal static bool TryGetPluginConfig(PluginInfo pluginInfo, out ConfigFile config)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			config = null;
			if (pluginInfo == null || pluginInfo.Instance == null)
			{
				Log.LogWarning("Null PluginInfo!");
				return false;
			}
			config = (ConfigFile)ConfigGetterInfo.Invoke(pluginInfo.Instance, null);
			return config != null;
		}

		private void UpdatePlugin(bool saveConfig = true, bool initialUpdate = false)
		{
			if (saveConfig)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
		}

		public void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPrefix]
		[HarmonyPriority(200)]
		[HarmonyPatch(typeof(FejdStartup), "Start")]
		internal static void ScanPluginConfigFiles()
		{
			Log.LogInfo("Prefix FjedStartup.Start", Log.InfoLevel.Medium);
			foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
			{
				if (!KeyBindManager.PluginConfigsMap.ContainsKey(pluginInfo.Key) && !(pluginInfo.Key == "Searica.Valheim.KeyBindManager"))
				{
					if (!KeyBindManager.TryGetPluginConfig(pluginInfo.Value, out var config))
					{
						Log.LogWarning($"Failed to get config for {pluginInfo.Value}");
						continue;
					}
					KeyBindManager.PluginConfigsMap.Add(pluginInfo.Key, config);
					Log.LogInfo($"Found config for {pluginInfo.Value}");
				}
			}
		}

		[HarmonyPrefix]
		[HarmonyPriority(100)]
		[HarmonyPatch(typeof(ZoneSystem), "Start")]
		internal static void ScanForKeyBinds()
		{
			Log.LogInfo("Prefix ZoneSystem.Start", Log.InfoLevel.Medium);
			foreach (KeyValuePair<string, ConfigFile> item in KeyBindManager.PluginConfigsMap)
			{
				if (item.Value == null)
				{
					continue;
				}
				if (!KeyBindManager.ConfigHandlers.ContainsKey(item.Key))
				{
					KeyBindManager.ConfigHandlers.Add(item.Key, new Dictionary<ConfigDefinition, KeyBindManager.ConfigHandlerDB>());
				}
				Log.LogInfo("Scanning configs for " + item.Key, Log.InfoLevel.Medium);
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item2 in item.Value)
				{
					Log.LogInfo("Config Entry: " + item2.Key.Key, Log.InfoLevel.High);
					ConfigDefinition key = item2.Key;
					ConfigEntryBase value = item2.Value;
					Type type;
					if (KeyBindManager.ConfigHandlers[item.Key].ContainsKey(key) || KeyBindManager.IgnoreConfigList.Contains(key))
					{
						Log.LogInfo("Already scanned, skipping config entry", Log.InfoLevel.High);
					}
					else if (IsKeyBindConfig(value, out type))
					{
						Log.LogInfo("Adding keybind handler", Log.InfoLevel.High);
						KeyBindManager.ConfigHandlers[item.Key].Add(key, new KeyBindManager.ConfigHandlerDB(item.Key, value, type));
					}
					else
					{
						Log.LogInfo("Not a keybind, skipping config entry", Log.InfoLevel.High);
						KeyBindManager.IgnoreConfigList.Add(key);
					}
				}
			}
		}

		internal static bool IsKeyBindConfig(ConfigEntryBase configEntry, out Type type)
		{
			type = configEntry.SettingType;
			if (type == typeof(KeyCode) || type == typeof(KeyboardShortcut))
			{
				return true;
			}
			if (type == typeof(string))
			{
				return HasKeyBindDesc(configEntry);
			}
			return false;
		}

		internal static bool HasKeyBindDesc(ConfigEntryBase configEntry)
		{
			string text = configEntry.Description.Description.ToLowerInvariant();
			foreach (string keyBindDescHint in KeyBindManager.KeyBindDescHints)
			{
				if (text.Contains(keyBindDescHint))
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace DiscoveryPins.Extensions
{
	internal static class SafeInvokEvents
	{
		public static void SafeInvoke(this Action events)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action action = (Action)invocationList[i];
				try
				{
					action();
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1>(this Action<TArg1> events, TArg1 arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1> action = (Action<TArg1>)invocationList[i];
				try
				{
					action(arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TArg1, TArg2>(this Action<TArg1, TArg2> events, TArg1 arg1, TArg2 arg2)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				Action<TArg1, TArg2> action = (Action<TArg1, TArg2>)invocationList[i];
				try
				{
					action(arg1, arg2);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{ex}");
				}
			}
		}

		public static void SafeInvoke<TEventArg>(this EventHandler<TEventArg> events, object sender, TEventArg arg1)
		{
			if (events == null)
			{
				return;
			}
			Delegate[] invocationList = events.GetInvocationList();
			for (int i = 0; i < invocationList.Length; i++)
			{
				EventHandler<TEventArg> eventHandler = (EventHandler<TEventArg>)invocationList[i];
				try
				{
					eventHandler(sender, arg1);
				}
				catch (Exception ex)
				{
					Log.LogWarning($"Exception thrown at event {new StackFrame(1).GetMethod().Name} in {eventHandler.Method.DeclaringType.Name}.{eventHandler.Method.Name}:\n{ex}");
				}
			}
		}
	}
}