Decompiled source of SearchableBuildMenu v1.0.4

SearchableBuildMenu.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
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.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SearchableBuildMenu.Utilities;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("SearchableBuildMenu")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Azumatt")]
[assembly: AssemblyProduct("SearchableBuildMenu")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")]
[assembly: AssemblyFileVersion("1.0.4")]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.4.0")]
[module: UnverifiableCode]
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 SearchableBuildMenu
{
	[HarmonyPatch(typeof(Hud), "Awake")]
	internal static class HudAwakePatch
	{
		private static void Postfix(Hud __instance)
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			SearchableBuildMenuPlugin.BuildSearchBox = Object.Instantiate<GameObject>(SearchableBuildMenuPlugin.Asset.LoadAsset<GameObject>("BuildPieceSearch"), __instance.m_pieceSelectionWindow.transform);
			((Object)SearchableBuildMenuPlugin.BuildSearchBox).name = "BuildPieceSearchBox";
			DragWindowCntrl.ApplyDragWindowCntrl(SearchableBuildMenuPlugin.BuildSearchBox);
			SearchableBuildMenuPlugin.BuildSearchInputField = SearchableBuildMenuPlugin.BuildSearchBox.GetComponentInChildren<TMP_InputField>();
			TMP_FontAsset font = ((Component)__instance.m_pieceDescription).GetComponentInChildren<TMP_Text>().font;
			SearchableBuildMenuPlugin.BuildSearchInputField.textComponent.font = font;
			((Component)SearchableBuildMenuPlugin.BuildSearchInputField.placeholder).GetComponentInChildren<TMP_Text>().font = font;
			RectTransform component = SearchableBuildMenuPlugin.BuildSearchBox.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(0f, 1f);
			component.pivot = new Vector2(0f, 1f);
			if (PlayerPrefs.HasKey("SearchableBuildMenuSearchBoxPosition"))
			{
				Vector2 anchoredPosition = StringToVector2(PlayerPrefs.GetString("SearchableBuildMenuSearchBoxPosition"));
				component.anchoredPosition = anchoredPosition;
			}
			else
			{
				component.anchoredPosition = new Vector2(-10f, 35f);
			}
			component.sizeDelta = new Vector2(200f, 30f);
			((UnityEvent<string>)(object)SearchableBuildMenuPlugin.BuildSearchInputField.onValueChanged).AddListener((UnityAction<string>)PieceTableUpdateAvailablePatch.OnSearchValueChanged);
		}

		internal static Vector2 StringToVector2(string s)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(s))
			{
				throw new ArgumentException("SearchableBuildMenuSearchBoxPosition Input string is null or empty.");
			}
			string[] array = s.Substring(1, s.Length - 2).Split(new char[1] { ',' });
			if (array.Length != 2)
			{
				throw new FormatException("SearchableBuildMenuSearchBoxPosition Input string was not in a correct format.");
			}
			return new Vector2(float.Parse(array[0]), float.Parse(array[1]));
		}
	}
	[HarmonyPatch(typeof(PieceTable), "UpdateAvailable")]
	internal static class PieceTableUpdateAvailablePatch
	{
		private static void Postfix(PieceTable __instance)
		{
			if ((Object)(object)SearchableBuildMenuPlugin.BuildSearchInputField == (Object)null)
			{
				return;
			}
			string searchText = SearchableBuildMenuPlugin.BuildSearchInputField.text.ToLower();
			if (string.IsNullOrEmpty(searchText))
			{
				return;
			}
			if (searchText.StartsWith("@", StringComparison.Ordinal))
			{
				string modIdentifier = searchText.Substring(1).ToLower();
				for (int i = 0; i < __instance.m_availablePieces.Count; i++)
				{
					__instance.m_availablePieces[i] = __instance.m_availablePieces[i].Where(delegate(Piece piece)
					{
						Assembly assemblyForPrefab = AssetLoadTracker.GetAssemblyForPrefab(((Object)((Component)piece).gameObject).name.ToLowerInvariant());
						return assemblyForPrefab != null && assemblyForPrefab.GetName().Name.ToLowerInvariant().Contains(modIdentifier);
					}).ToList();
				}
				return;
			}
			if (searchText.StartsWith("!", StringComparison.Ordinal))
			{
				string searchQuery = searchText.Substring(1).ToLower();
				for (int j = 0; j < __instance.m_availablePieces.Count; j++)
				{
					__instance.m_availablePieces[j] = __instance.m_availablePieces[j].Where((Piece piece) => piece.m_resources.Any((Requirement resource) => Localization.instance.Localize(resource.m_resItem?.m_itemData?.m_shared?.m_name).ToLower().Contains(searchQuery))).ToList();
				}
				return;
			}
			for (int k = 0; k < __instance.m_availablePieces.Count; k++)
			{
				__instance.m_availablePieces[k] = __instance.m_availablePieces[k].Where((Piece piece) => piece.m_name.ToLower().Contains(searchText) || piece.m_description.ToLower().Contains(searchText) || Localization.instance.Localize(piece.m_name).ToLower().Contains(searchText) || Localization.instance.Localize(piece.m_description).ToLower().Contains(searchText)).ToList();
			}
		}

		internal static void OnSearchValueChanged(string searchText)
		{
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)localPlayer == (Object)null))
			{
				if (!string.IsNullOrEmpty(searchText))
				{
					localPlayer.UpdateAvailablePiecesList();
				}
				else if (((Humanoid)localPlayer).m_rightItem != null && Object.op_Implicit((Object)(object)((Humanoid)localPlayer).m_rightItem.m_shared.m_buildPieces))
				{
					((Humanoid)localPlayer).SetPlaceMode(((Humanoid)localPlayer).m_rightItem.m_shared.m_buildPieces);
				}
				else
				{
					((Humanoid)localPlayer).SetPlaceMode((PieceTable)null);
				}
			}
		}
	}
	[HarmonyPatch(typeof(TextInput), "IsVisible")]
	internal static class TextInputIsVisiblePatch
	{
		private static void Postfix(TextInput __instance, ref bool __result)
		{
			if (SearchableBuildMenuPlugin.BuildSearchInputField.isFocused)
			{
				__result = true;
			}
		}
	}
	[HarmonyPatch(typeof(Player), "CopyPiece")]
	internal static class ClearSearchInputOnCopy
	{
		private static void Prefix(Player __instance)
		{
			if (!((Object)(object)SearchableBuildMenuPlugin.BuildSearchInputField == (Object)null))
			{
				SearchableBuildMenuPlugin.BuildSearchInputField.text = string.Empty;
				((UnityEvent<string>)(object)SearchableBuildMenuPlugin.BuildSearchInputField.onValueChanged).Invoke(SearchableBuildMenuPlugin.BuildSearchInputField.text);
			}
		}
	}
	[BepInPlugin("Azumatt.SearchableBuildMenu", "SearchableBuildMenu", "1.0.4")]
	public class SearchableBuildMenuPlugin : BaseUnityPlugin
	{
		public enum Toggle
		{
			On = 1,
			Off = 0
		}

		internal const string ModName = "SearchableBuildMenu";

		internal const string ModVersion = "1.0.4";

		internal const string Author = "Azumatt";

		private const string ModGUID = "Azumatt.SearchableBuildMenu";

		private readonly Harmony _harmony = new Harmony("Azumatt.SearchableBuildMenu");

		public static readonly ManualLogSource SearchableBuildMenuLogger = Logger.CreateLogSource("SearchableBuildMenu");

		internal static AssetBundle Asset = null;

		internal static GameObject BuildSearchBox = null;

		internal static TMP_InputField BuildSearchInputField = null;

		public void Awake()
		{
			LoadAssets();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			_harmony.PatchAll(executingAssembly);
		}

		private static AssetBundle GetAssetBundleFromResources(string filename)
		{
			string filename2 = filename;
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename2));
			using Stream stream = executingAssembly.GetManifestResourceStream(name);
			return AssetBundle.LoadFromStream(stream);
		}

		public static void LoadAssets()
		{
			Asset = GetAssetBundleFromResources("buildpiecesearch");
		}

		private void Start()
		{
			AssetLoadTracker.MapPrefabsToBundles();
			AssetLoadTracker.MapBundlesToAssemblies();
		}
	}
}
namespace SearchableBuildMenu.Utilities
{
	public class AssetLoadTracker
	{
		private static readonly Dictionary<string, string> PrefabToBundleMapping = new Dictionary<string, string>();

		private static readonly Dictionary<string, Assembly> BundleToAssemblyMapping = new Dictionary<string, Assembly>();

		internal static void MapPrefabsToBundles()
		{
			foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles())
			{
				foreach (string item in from name in allLoadedAssetBundle.GetAllAssetNames()
					where name.EndsWith(".prefab")
					select name)
				{
					string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(item);
					PrefabToBundleMapping[fileNameWithoutExtension] = ((Object)allLoadedAssetBundle).name;
				}
			}
		}

		internal static void MapBundlesToAssemblies()
		{
			List<Assembly> list = Chainloader.PluginInfos.Select((KeyValuePair<string, PluginInfo> keyValuePair) => ((object)keyValuePair.Value.Instance).GetType().Assembly).ToList();
			foreach (string bundleName in PrefabToBundleMapping.Values.Distinct())
			{
				foreach (Assembly item in list)
				{
					try
					{
						if (item.GetManifestResourceNames().Any((string resourceName) => resourceName.EndsWith(bundleName)))
						{
							BundleToAssemblyMapping[bundleName] = item;
							break;
						}
					}
					catch (Exception arg)
					{
						SearchableBuildMenuPlugin.SearchableBuildMenuLogger.LogError((object)$"Error while getting manifest resource names for assembly {item.GetName().Name}: {arg}");
					}
				}
			}
		}

		public static Assembly? GetAssemblyForPrefab(string prefabName)
		{
			if (PrefabToBundleMapping.TryGetValue(prefabName, out string value) && BundleToAssemblyMapping.TryGetValue(value, out Assembly value2))
			{
				return value2;
			}
			return null;
		}

		public static string GetBundleForPrefab(string prefabName)
		{
			if (!PrefabToBundleMapping.TryGetValue(prefabName, out string value))
			{
				return "";
			}
			return value;
		}
	}
	public class DragWindowCntrl : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler
	{
		private float size;

		private float _scale = 1f;

		private RectTransform _window;

		private Vector2 _delta;

		private Image draggingImage;

		public static void ApplyDragWindowCntrl(GameObject go)
		{
			go.AddComponent<DragWindowCntrl>();
		}

		private void Awake()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			_window = (RectTransform)((Component)this).transform;
			Transform obj = Utils.FindChild(((Component)this).transform, "DraggingImage", (IterativeSearchType)0);
			draggingImage = ((obj != null) ? ((Component)obj).GetComponent<Image>() : null);
			if (!((Object)(object)draggingImage == (Object)null))
			{
				((Behaviour)draggingImage).enabled = false;
			}
		}

		private void Start()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = default(Vector2);
			if (PlayerPrefs.HasKey("SearchableBuildMenuSearchBoxPosition"))
			{
				val = HudAwakePatch.StringToVector2(PlayerPrefs.GetString("SearchableBuildMenuSearchBoxPosition"));
			}
			else
			{
				((Vector2)(ref val))..ctor(-10f, 35f);
			}
			val = GetCorrectedPositionIfOffScreen(val);
			_window.anchoredPosition = val;
			size = _window.sizeDelta.x;
			_scale = ((Transform)_window).localScale.x;
		}

		private void Update()
		{
			((Selectable)SearchableBuildMenuPlugin.BuildSearchInputField).interactable = !Input.GetKey((KeyCode)306);
			if ((Object)(object)draggingImage != (Object)null)
			{
				((Behaviour)draggingImage).enabled = Input.GetKey((KeyCode)306);
			}
		}

		public void OnBeginDrag(PointerEventData eventData)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_window).parent;
			Vector2 val = default(Vector2);
			RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((parent is RectTransform) ? parent : null), eventData.position, eventData.pressEventCamera, ref val);
			_delta = val - _window.anchoredPosition;
		}

		public void OnDrag(PointerEventData eventData)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_window).parent;
			Vector2 val = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((parent is RectTransform) ? parent : null), eventData.position, eventData.pressEventCamera, ref val))
			{
				Vector2 anchoredPosition = val - _delta;
				_window.anchoredPosition = anchoredPosition;
			}
		}

		public void OnEndDrag(PointerEventData eventData)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			Vector2 correctedPositionIfOffScreen = GetCorrectedPositionIfOffScreen(_window.anchoredPosition);
			_window.anchoredPosition = correctedPositionIfOffScreen;
			PlayerPrefs.SetString("SearchableBuildMenuSearchBoxPosition", ((object)(Vector2)(ref correctedPositionIfOffScreen)).ToString());
			PlayerPrefs.Save();
		}

		private Vector2 GetCorrectedPositionIfOffScreen(Vector2 position)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			CanvasScaler val = Object.FindObjectOfType<CanvasScaler>();
			float num = (float)Screen.width / val.scaleFactor;
			float num2 = (float)Screen.height / val.scaleFactor;
			Rect rect = _window.rect;
			float num3 = ((Rect)(ref rect)).width / 2f;
			float num4 = ((Rect)(ref rect)).height / 2f;
			Vector2 result = default(Vector2);
			((Vector2)(ref result))..ctor(-10f, 35f);
			if (!(position.x + num3 < 0f) && !(position.x - num3 > num) && !(position.y + num4 < 0f) && !(position.y - num4 > num2))
			{
				return position;
			}
			return result;
		}
	}
}