Decompiled source of BlueprintSearch v1.0.0

BlueprintSearch.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BlueprintSearch.Patches;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BlueprintSearch")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Search bar for the blueprint browser / 蓝图库搜索栏")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+113ddcdf68e120a3d7a47cab31d7c95509e1afd0")]
[assembly: AssemblyProduct("BlueprintSearch")]
[assembly: AssemblyTitle("BlueprintSearch")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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 BlueprintSearch
{
	[BepInPlugin("org.fyyy.blueprintsearch", "BlueprintSearch", "1.0.0")]
	public class BlueprintSearchPlugin : BaseUnityPlugin
	{
		public static readonly ManualLogSource Logger = Logger.CreateLogSource("BlueprintSearch");

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<int> MaxResults;

		internal static ConfigEntry<int> DebounceMs;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable search bar in blueprint browser / 在蓝图库窗口启用搜索栏");
			ModEnabled.SettingChanged += OnEnabledChanged;
			MaxResults = ((BaseUnityPlugin)this).Config.Bind<int>("General", "MaxResults", 0, "Hard cap on total search results. 0 = unlimited. Results are rendered progressively across frames, so the cap is only needed for libraries so large that even streamed rendering is undesirable.");
			DebounceMs = ((BaseUnityPlugin)this).Config.Bind<int>("General", "DebounceMs", 120, "Milliseconds to wait after the last keystroke before recomputing results");
			_harmony = new Harmony("org.fyyy.blueprintsearch");
			ApplyPatches();
			Logger.LogInfo((object)"BlueprintSearch loaded.");
		}

		private void OnDestroy()
		{
			if (ModEnabled != null)
			{
				ModEnabled.SettingChanged -= OnEnabledChanged;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private void ApplyPatches()
		{
			if (ModEnabled.Value)
			{
				_harmony.PatchAll(typeof(UIBlueprintBrowserPatches));
				_harmony.PatchAll(typeof(UIBlueprintFileItemPatches));
			}
		}

		private void OnEnabledChanged(object sender, EventArgs e)
		{
			_harmony.UnpatchSelf();
			SearchState.cacheDirty = true;
			ApplyPatches();
			SearchBarUI searchBarUI = UIBlueprintBrowserPatches.searchBarUI;
			if ((Object)(object)searchBarUI != (Object)null)
			{
				((Component)searchBarUI).gameObject.SetActive(ModEnabled.Value);
				if (!ModEnabled.Value)
				{
					SearchState.ClearQuery();
					if ((Object)(object)searchBarUI.browser != (Object)null && searchBarUI.browser.currentDirectoryInfo != null)
					{
						searchBarUI.browser.SetCurrentDirectory(searchBarUI.browser.currentDirectoryInfo.FullName);
					}
				}
			}
			Logger.LogInfo((object)("BlueprintSearch " + (ModEnabled.Value ? "enabled" : "disabled") + "."));
		}
	}
	internal class SearchBarUI : MonoBehaviour
	{
		private const float BarHeight = 24f;

		private const float ClearButtonWidth = 24f;

		private const float BarBottomGap = 4f;

		internal UIBlueprintBrowser browser;

		internal InputField inputField;

		internal Button clearButton;

		internal static SearchBarUI Create(UIBlueprintBrowser browser)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)((Component)browser.browserScroll).transform;
			GameObject val2 = new GameObject("BlueprintSearchBar", new Type[1] { typeof(RectTransform) });
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent(((Transform)val).parent, false);
			float y = val.offsetMax.y;
			val3.anchorMin = new Vector2(val.anchorMin.x, 1f);
			val3.anchorMax = new Vector2(val.anchorMax.x, 1f);
			val3.pivot = new Vector2(0.5f, 1f);
			val3.offsetMin = new Vector2(val.offsetMin.x, y - 24f);
			val3.offsetMax = new Vector2(val.offsetMax.x, y);
			val.offsetMax = new Vector2(val.offsetMax.x, y - 24f - 4f);
			SearchBarUI searchBarUI = val2.AddComponent<SearchBarUI>();
			searchBarUI.browser = browser;
			searchBarUI.BuildInputField(val3);
			searchBarUI.BuildClearButton(val3);
			searchBarUI.RefreshPlaceholder();
			return searchBarUI;
		}

		private void BuildInputField(RectTransform parent)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Input", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(InputField)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = new Vector2(0f, 0f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(0f, 0.5f);
			val2.offsetMin = new Vector2(0f, 0f);
			val2.offsetMax = new Vector2(-28f, 0f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.35f);
			GameObject val3 = new GameObject("Text", new Type[2]
			{
				typeof(RectTransform),
				typeof(Text)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = new Vector2(6f, 2f);
			val4.offsetMax = new Vector2(-6f, -2f);
			Text component = val3.GetComponent<Text>();
			component.supportRichText = false;
			((Graphic)component).color = Color.white;
			component.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			component.fontSize = 14;
			component.alignment = (TextAnchor)3;
			GameObject val5 = new GameObject("Placeholder", new Type[2]
			{
				typeof(RectTransform),
				typeof(Text)
			});
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent((Transform)(object)val2, false);
			val6.anchorMin = Vector2.zero;
			val6.anchorMax = Vector2.one;
			val6.offsetMin = new Vector2(6f, 2f);
			val6.offsetMax = new Vector2(-6f, -2f);
			Text component2 = val5.GetComponent<Text>();
			((Graphic)component2).color = new Color(1f, 1f, 1f, 0.45f);
			component2.font = component.font;
			component2.fontSize = 14;
			component2.alignment = (TextAnchor)3;
			component2.fontStyle = (FontStyle)2;
			inputField = val.GetComponent<InputField>();
			inputField.textComponent = component;
			inputField.placeholder = (Graphic)(object)component2;
			inputField.lineType = (LineType)0;
			((UnityEvent<string>)(object)inputField.onValueChanged).AddListener((UnityAction<string>)OnValueChanged);
		}

		private void BuildClearButton(RectTransform parent)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Expected O, but got Unknown
			GameObject val = new GameObject("Clear", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Button)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			val2.anchorMin = new Vector2(1f, 0f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(1f, 0.5f);
			val2.anchoredPosition = new Vector2(0f, 0f);
			val2.sizeDelta = new Vector2(24f, 0f);
			((Graphic)val.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.25f);
			GameObject val3 = new GameObject("Label", new Type[2]
			{
				typeof(RectTransform),
				typeof(Text)
			});
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val2, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.offsetMin = Vector2.zero;
			val4.offsetMax = Vector2.zero;
			Text component = val3.GetComponent<Text>();
			component.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
			component.fontSize = 16;
			((Graphic)component).color = Color.white;
			component.alignment = (TextAnchor)4;
			component.text = "×";
			clearButton = val.GetComponent<Button>();
			((UnityEvent)clearButton.onClick).AddListener(new UnityAction(OnClearClicked));
		}

		internal void RefreshPlaceholder()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			bool flag = Localization.CurrentLanguage != null && Localization.CurrentLanguage.lcId == 2052;
			((Text)inputField.placeholder).text = (flag ? "搜索蓝图..." : "Search blueprints...");
		}

		private void OnValueChanged(string text)
		{
			SearchState.query = text;
			SearchState.lastChangeTime = Time.unscaledTime;
			SearchState.pendingRefresh = true;
		}

		private void OnClearClicked()
		{
			inputField.SetTextWithoutNotify("");
			SearchState.ClearQuery();
			if ((Object)(object)browser != (Object)null && browser.currentDirectoryInfo != null)
			{
				browser.SetCurrentDirectory(browser.currentDirectoryInfo.FullName);
			}
		}

		private void Update()
		{
			if (SearchState.pendingRefresh)
			{
				float num = (float)(BlueprintSearchPlugin.DebounceMs?.Value ?? 120) * 0.001f;
				if (Time.unscaledTime - SearchState.lastChangeTime >= num)
				{
					SearchState.pendingRefresh = false;
					SearchState.tokens = SearchFilter.Tokenize(SearchState.query);
					if ((Object)(object)browser != (Object)null && browser.currentDirectoryInfo != null)
					{
						browser.SetCurrentDirectory(browser.currentDirectoryInfo.FullName);
					}
				}
			}
			UIBlueprintBrowserPatches.ContinueStreaming();
		}
	}
	internal static class SearchFilter
	{
		private static readonly char[] Separators = new char[4] { ' ', '\t', '/', '\\' };

		internal static string[] Tokenize(string query)
		{
			if (string.IsNullOrWhiteSpace(query))
			{
				return Array.Empty<string>();
			}
			return query.ToLowerInvariant().Split(Separators, StringSplitOptions.RemoveEmptyEntries);
		}

		internal static bool Matches(string pathLower, string[] tokens)
		{
			for (int i = 0; i < tokens.Length; i++)
			{
				if (pathLower.IndexOf(tokens[i], StringComparison.Ordinal) < 0)
				{
					return false;
				}
			}
			return true;
		}
	}
	internal static class SearchState
	{
		internal struct PathEntry
		{
			public string relLower;

			public string relOriginal;
		}

		internal static string query = "";

		internal static string[] tokens = Array.Empty<string>();

		internal static readonly List<PathEntry> cachedEntries = new List<PathEntry>();

		internal static bool cacheDirty = true;

		internal static float lastChangeTime;

		internal static bool pendingRefresh;

		internal static bool Active => tokens.Length != 0;

		internal static void RebuildCache(string rootPath, int rootPathLen, ManualLogSource logger)
		{
			cachedEntries.Clear();
			if (!Directory.Exists(rootPath))
			{
				cacheDirty = false;
				return;
			}
			EnumerateDirectory(rootPath, rootPathLen, logger);
			cacheDirty = false;
		}

		private static void EnumerateDirectory(string dirFull, int rootPathLen, ManualLogSource logger)
		{
			string[] files;
			string[] directories;
			try
			{
				files = Directory.GetFiles(dirFull, "*.txt", SearchOption.TopDirectoryOnly);
				directories = Directory.GetDirectories(dirFull, "*", SearchOption.TopDirectoryOnly);
			}
			catch (Exception ex)
			{
				logger.LogWarning((object)("BlueprintSearch: skipping " + dirFull + ": " + ex.GetType().Name + ": " + ex.Message));
				return;
			}
			string[] array = files;
			foreach (string text in array)
			{
				if (text.Length > rootPathLen)
				{
					string text2 = text.Substring(rootPathLen).Replace('\\', '/');
					cachedEntries.Add(new PathEntry
					{
						relLower = text2.ToLowerInvariant(),
						relOriginal = text2
					});
				}
			}
			array = directories;
			for (int i = 0; i < array.Length; i++)
			{
				EnumerateDirectory(array[i], rootPathLen, logger);
			}
		}

		internal static void ClearQuery()
		{
			query = "";
			tokens = Array.Empty<string>();
			pendingRefresh = false;
		}

		internal static void Reset()
		{
			ClearQuery();
			cachedEntries.Clear();
			cacheDirty = true;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "org.fyyy.blueprintsearch";

		public const string PLUGIN_NAME = "BlueprintSearch";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace BlueprintSearch.Patches
{
	internal static class UIBlueprintBrowserPatches
	{
		internal static SearchBarUI searchBarUI;

		private const int MatchesPerFrame = 16;

		private const int ScanPerFrame = 5000;

		private static UIBlueprintBrowser _streamBrowser;

		private static int _streamNextIndex;

		private static int _streamMatches;

		private static int _streamY;

		private static readonly MethodInfo GetOrCreateFileItemMI = AccessTools.Method(typeof(UIBlueprintBrowser), "GetOrCreateFileItem", (Type[])null, (Type[])null);

		private static bool _missingMIReported;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "_OnCreate")]
		private static void OnCreate_Postfix(UIBlueprintBrowser __instance)
		{
			if (!((Object)(object)searchBarUI != (Object)null))
			{
				searchBarUI = SearchBarUI.Create(__instance);
			}
		}

		private static void UpdateToolbarInteractable(UIBlueprintBrowser browser)
		{
			bool interactable = !SearchState.Active;
			((Selectable)browser.cutButton).interactable = interactable;
			((Selectable)browser.newFileButton).interactable = interactable;
			((Selectable)browser.newFolderButton).interactable = interactable;
			((Selectable)browser.upLevelButton).interactable = interactable;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "_OnOpen")]
		private static void OnOpen_Postfix(UIBlueprintBrowser __instance)
		{
			if ((Object)(object)searchBarUI != (Object)null && (Object)(object)searchBarUI.inputField != (Object)null)
			{
				searchBarUI.inputField.SetTextWithoutNotify("");
			}
			if ((Object)(object)searchBarUI != (Object)null)
			{
				searchBarUI.RefreshPlaceholder();
			}
			SearchState.ClearQuery();
			if (SearchState.cacheDirty)
			{
				int rootPathLen = ((__instance.rootPath != null) ? __instance.rootPath.Length : 0);
				SearchState.RebuildCache(__instance.rootPath, rootPathLen, BlueprintSearchPlugin.Logger);
			}
			UpdateToolbarInteractable(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "_OnClose")]
		private static void OnClose_Postfix(UIBlueprintBrowser __instance)
		{
			CancelStreaming();
			SearchState.ClearQuery();
			if ((Object)(object)__instance != (Object)null)
			{
				UpdateToolbarInteractable(__instance);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "SetCurrentDirectory")]
		private static void SetCurrentDirectory_Postfix(UIBlueprintBrowser __instance)
		{
			UpdateToolbarInteractable(__instance);
			if (SearchState.Active)
			{
				RepopulateWithResults(__instance);
			}
		}

		internal static void CancelStreaming()
		{
			_streamBrowser = null;
			_streamNextIndex = 0;
			_streamMatches = 0;
			_streamY = 0;
		}

		private static void RepopulateWithResults(UIBlueprintBrowser browser)
		{
			foreach (UIBlueprintFileItem fileItem in browser.fileItems)
			{
				if (((ManualBehaviour)fileItem).inited)
				{
					((ManualBehaviour)fileItem)._Free();
				}
			}
			_streamBrowser = browser;
			_streamNextIndex = 0;
			_streamMatches = 0;
			_streamY = 0;
			RunStreamBatch();
		}

		internal static void ContinueStreaming()
		{
			if (!((Object)(object)_streamBrowser == (Object)null))
			{
				if (!SearchState.Active)
				{
					CancelStreaming();
				}
				else if (!SearchState.pendingRefresh)
				{
					RunStreamBatch();
				}
			}
		}

		private static void RunStreamBatch()
		{
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			UIBlueprintBrowser streamBrowser = _streamBrowser;
			List<SearchState.PathEntry> cachedEntries = SearchState.cachedEntries;
			int num = BlueprintSearchPlugin.MaxResults?.Value ?? 0;
			int num2 = 0;
			int num3 = 0;
			bool flag = false;
			while (num2 < 16 && num3 < 5000 && _streamNextIndex < cachedEntries.Count)
			{
				if (num > 0 && _streamMatches >= num)
				{
					flag = true;
					break;
				}
				int index = _streamNextIndex++;
				num3++;
				if (SearchFilter.Matches(cachedEntries[index].relLower, SearchState.tokens))
				{
					string relOriginal = cachedEntries[index].relOriginal;
					string text = streamBrowser.rootPath + relOriginal;
					string text2 = ComposeLabel(relOriginal);
					UIBlueprintFileItem orCreateFileItemViaReflection = GetOrCreateFileItemViaReflection(streamBrowser);
					if ((Object)(object)orCreateFileItemViaReflection == (Object)null)
					{
						_streamNextIndex = cachedEntries.Count;
						break;
					}
					((ManualBehaviour)orCreateFileItemViaReflection)._Init(((ManualBehaviour)streamBrowser).data);
					_streamY = orCreateFileItemViaReflection.SetItemLayout(_streamMatches, false, text, text2);
					((ManualBehaviour)orCreateFileItemViaReflection)._Open();
					_streamMatches++;
					num2++;
				}
			}
			if (num2 > 0)
			{
				streamBrowser.contentTrans.sizeDelta = new Vector2(streamBrowser.contentTrans.sizeDelta.x, (float)_streamY);
			}
			if (flag || _streamNextIndex >= cachedEntries.Count || (num > 0 && _streamMatches >= num))
			{
				((Component)streamBrowser.emptyTipText).gameObject.SetActive(_streamMatches == 0);
				CancelStreaming();
			}
			else
			{
				((Component)streamBrowser.emptyTipText).gameObject.SetActive(false);
			}
		}

		private static UIBlueprintFileItem GetOrCreateFileItemViaReflection(UIBlueprintBrowser browser)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			if (GetOrCreateFileItemMI == null)
			{
				if (!_missingMIReported)
				{
					_missingMIReported = true;
					BlueprintSearchPlugin.Logger.LogError((object)"BlueprintSearch: UIBlueprintBrowser.GetOrCreateFileItem not found — search results disabled.");
				}
				return null;
			}
			return (UIBlueprintFileItem)GetOrCreateFileItemMI.Invoke(browser, null);
		}

		internal static string ComposeLabel(string relPath)
		{
			string text = (relPath.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) ? relPath.Substring(0, relPath.Length - 4) : relPath);
			int num = text.LastIndexOf('/');
			if (num <= 0)
			{
				return text.Substring(num + 1);
			}
			string text2 = text.Substring(num + 1);
			int num2 = text.LastIndexOf('/', num - 1);
			return ((num2 < 0) ? text.Substring(0, num) : text.Substring(num2 + 1, num - num2 - 1)) + " / " + text2;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "OnNewFileButtonClick")]
		private static void OnNewFileButtonClick_Postfix()
		{
			SearchState.cacheDirty = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBrowser), "OnNewFolderButtonClick")]
		private static void OnNewFolderButtonClick_Postfix()
		{
			SearchState.cacheDirty = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintInspector), "OnDeleteClick")]
		private static void InspectorOnDeleteClick_Postfix()
		{
			SearchState.cacheDirty = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintInspector), "OnSaveChangesClick")]
		private static void InspectorOnSaveChangesClick_Postfix()
		{
			SearchState.cacheDirty = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintBookInspector), "DoDeleteBook")]
		private static void BookInspectorDoDeleteBook_Postfix()
		{
			SearchState.cacheDirty = true;
		}
	}
	internal static class UIBlueprintFileItemPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(UIBlueprintFileItem), "_OnRegEvent")]
		private static void OnRegEvent_Postfix(UIBlueprintFileItem __instance)
		{
			GameObject gameObject = ((Component)__instance.button).gameObject;
			BlueprintItemRightClickHandler blueprintItemRightClickHandler = gameObject.GetComponent<BlueprintItemRightClickHandler>();
			if ((Object)(object)blueprintItemRightClickHandler == (Object)null)
			{
				blueprintItemRightClickHandler = gameObject.AddComponent<BlueprintItemRightClickHandler>();
			}
			blueprintItemRightClickHandler.item = __instance;
		}
	}
	internal class BlueprintItemRightClickHandler : MonoBehaviour, IPointerClickHandler, IEventSystemHandler
	{
		internal UIBlueprintFileItem item;

		public void OnPointerClick(PointerEventData eventData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)eventData.button != 1 || !SearchState.Active || (Object)(object)item == (Object)null || item.isDirectory)
			{
				return;
			}
			string directoryName = Path.GetDirectoryName(item.fullPath);
			if (!string.IsNullOrEmpty(directoryName))
			{
				UIBlueprintBrowser val = (((Object)(object)UIBlueprintBrowserPatches.searchBarUI != (Object)null) ? UIBlueprintBrowserPatches.searchBarUI.browser : null);
				if (!((Object)(object)val == (Object)null))
				{
					UIBlueprintBrowserPatches.searchBarUI.inputField.SetTextWithoutNotify("");
					SearchState.ClearQuery();
					val.SetCurrentDirectory(directoryName);
				}
			}
		}
	}
}