Decompiled source of CraftingFilter v0.9.1

CraftingFilter.dll

Decompiled a year 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 BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
public class AedenthornUtils
{
	public static bool IgnoreKeyPresses(bool extra = false)
	{
		int result;
		if (!extra)
		{
			if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
			{
				Chat instance = Chat.instance;
				if (instance == null || !instance.HasFocus())
				{
					result = (Menu.IsVisible() ? 1 : 0);
					goto IL_005f;
				}
			}
			result = 1;
			goto IL_005f;
		}
		int result2;
		if (!((Object)(object)ZNetScene.instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && !Minimap.IsOpen() && !Console.IsVisible() && !TextInput.IsVisible() && !ZNet.instance.InPasswordDialog())
		{
			Chat instance2 = Chat.instance;
			if ((instance2 == null || !instance2.HasFocus()) && !StoreGui.IsVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible())
			{
				TextViewer instance3 = TextViewer.instance;
				result2 = ((instance3 != null && instance3.IsVisible()) ? 1 : 0);
				goto IL_00d9;
			}
		}
		result2 = 1;
		goto IL_00d9;
		IL_005f:
		return (byte)result != 0;
		IL_00d9:
		return (byte)result2 != 0;
	}

	public static bool CheckKeyDown(string value)
	{
		try
		{
			return Input.GetKeyDown(value.ToLower());
		}
		catch
		{
			return false;
		}
	}

	public static bool CheckKeyHeld(string value, bool req = true)
	{
		try
		{
			return Input.GetKey(value.ToLower());
		}
		catch
		{
			return !req;
		}
	}
}
namespace CraftingFilter;

[BepInPlugin("aedenthorn.CraftingFilter", "Crafting Filter", "0.9.0")]
public class BepInExPlugin : BaseUnityPlugin
{
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
	private static class UpdateRecipeList_Patch
	{
		private static void Prefix(ref List<Recipe> recipes)
		{
			if (modEnabled.Value && Object.op_Implicit((Object)(object)Player.m_localPlayer.GetCurrentCraftingStation()))
			{
				Dbgl("updating recipes");
				GetFilteredRecipes(ref recipes);
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	private static class Hide_Patch
	{
		private static void Prefix()
		{
			if (modEnabled.Value)
			{
				((TMP_Text)((Component)InventoryGui.instance.m_tabCraft).gameObject.GetComponentInChildren<TextMeshProUGUI>()).text = Localization.instance.Localize("$inventory_craftbutton");
				lastCategoryIndex = 0;
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")]
	private static class OnTabCraftPressed_Patch
	{
		private static void Prefix()
		{
			if (modEnabled.Value)
			{
				Dbgl("Tab craft pressed");
				tabCraftPressed = 2;
			}
		}
	}

	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	private static class InventoryGui_Awake_Patch
	{
		private static void Postfix(InventoryGui __instance)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			if (!modEnabled.Value)
			{
				return;
			}
			dropDownList.Clear();
			for (int i = 0; i < categoryNames.Count; i++)
			{
				int idx = i;
				GameObject val = Object.Instantiate<GameObject>(((Component)__instance.m_tabCraft).gameObject);
				((Object)val).name = categoryNames[i];
				val.transform.SetParent(((Component)__instance.m_tabCraft).gameObject.transform.parent.parent);
				((Selectable)val.GetComponent<Button>()).interactable = true;
				val.GetComponent<Button>().onClick = new ButtonClickedEvent();
				((UnityEvent)val.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
				{
					SwitchFilter(idx);
				});
				val.SetActive(false);
				dropDownList.Add(val);
			}
		}
	}

	[HarmonyPatch(typeof(Terminal), "InputText")]
	private static class InputText_Patch
	{
		private static bool Prefix(Terminal __instance)
		{
			if (!modEnabled.Value)
			{
				return true;
			}
			string text = ((TMP_InputField)__instance.m_input).text;
			if (text.ToLower().Equals(typeof(BepInExPlugin).Namespace.ToLower() + " reset"))
			{
				((BaseUnityPlugin)context).Config.Reload();
				((BaseUnityPlugin)context).Config.Save();
				__instance.AddString(text);
				__instance.AddString(((BaseUnityPlugin)context).Info.Metadata.Name + " config reloaded");
				return false;
			}
			return true;
		}
	}

	public static ConfigEntry<bool> modEnabled;

	public static ConfigEntry<bool> isDebug;

	public static ConfigEntry<int> nexusID;

	public static ConfigEntry<bool> useScrollWheel;

	public static ConfigEntry<bool> showMenu;

	public static ConfigEntry<string> scrollModKey;

	public static ConfigEntry<string> prevHotKey;

	public static ConfigEntry<string> nextHotKey;

	public static ConfigEntry<string> categoryFile;

	private static BepInExPlugin context;

	private static Dictionary<string, List<ItemType>> categoryDict = new Dictionary<string, List<ItemType>>();

	private static List<string> categoryNames = new List<string>();

	private static List<GameObject> dropDownList = new List<GameObject>();

	private static int lastCategoryIndex = 0;

	private Vector3 lastMousePos;

	private static bool isShowing = false;

	private static string assetPath;

	private static int tabCraftPressed = 0;

	public static void Dbgl(string str = "", bool pref = true)
	{
		if (isDebug.Value)
		{
			Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str));
		}
	}

	private void Awake()
	{
		context = this;
		modEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable this mod");
		isDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "IsDebug", true, "Enable debug logs");
		nexusID = ((BaseUnityPlugin)this).Config.Bind<int>("General", "NexusID", 1219, "Nexus mod ID for updates");
		nexusID.Value = 1219;
		useScrollWheel = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ScrollWheel", true, "Use scroll wheel to switch filter");
		showMenu = ((BaseUnityPlugin)this).Config.Bind<bool>("Settings", "ShowMenu", true, "Show filter menu on hover");
		scrollModKey = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "ScrollModKey", "", "Modifer key to allow scroll wheel change. Use https://docs.unity3d.com/Manual/class-InputManager.html");
		categoryFile = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "CategoryFile", "categories.json", "Category file name");
		prevHotKey = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "HotKeyPrev", "", "Hotkey to switch to previous filter. Use https://docs.unity3d.com/Manual/class-InputManager.html");
		nextHotKey = ((BaseUnityPlugin)this).Config.Bind<string>("Settings", "HotKeyNext", "", "Hotkey to switch to next filter. Use https://docs.unity3d.com/Manual/class-InputManager.html");
		assetPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), typeof(BepInExPlugin).Namespace);
		LoadCategories();
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}

	private void LoadCategories()
	{
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		if (!Directory.Exists(assetPath))
		{
			Dbgl("Creating mod folder");
			Directory.CreateDirectory(assetPath);
		}
		string path = Path.Combine(assetPath, categoryFile.Value);
		CategoryData categoryData;
		if (!File.Exists(path))
		{
			Dbgl("Creating category file");
			categoryData = new CategoryData();
			File.WriteAllText(path, JsonUtility.ToJson((object)categoryData));
		}
		else
		{
			categoryData = JsonUtility.FromJson<CategoryData>(File.ReadAllText(path));
		}
		Dbgl("Loaded " + categoryData.categories.Count + " categories");
		categoryDict.Clear();
		categoryNames.Clear();
		foreach (string category in categoryData.categories)
		{
			if (!category.Contains(":"))
			{
				continue;
			}
			string[] array = category.Split(new char[1] { ':' });
			string[] array2 = array[1].Split(new char[1] { ',' });
			categoryNames.Add(array[0]);
			categoryDict[array[0]] = new List<ItemType>();
			string[] array3 = array2;
			foreach (string value in array3)
			{
				if (Enum.TryParse<ItemType>(value, out ItemType result))
				{
					categoryDict[array[0]].Add(result);
				}
			}
		}
		categoryNames.Sort(delegate(string a, string b)
		{
			if (categoryDict[a].Contains((ItemType)0))
			{
				return -1;
			}
			return categoryDict[b].Contains((ItemType)0) ? 1 : a.CompareTo(b);
		});
	}

	private void Update()
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009d: 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_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_0259: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		if (!modEnabled.Value || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || !InventoryGui.IsVisible() || (!Object.op_Implicit((Object)(object)Player.m_localPlayer.GetCurrentCraftingStation()) && !Player.m_localPlayer.NoCostCheat()))
		{
			lastCategoryIndex = 0;
			UpdateDropDown(show: false);
			return;
		}
		if (!InventoryGui.instance.InCraftTab())
		{
			UpdateDropDown(show: false);
			return;
		}
		bool flag = false;
		Vector3 mousePosition = Input.mousePosition;
		if (lastMousePos == Vector3.zero)
		{
			lastMousePos = mousePosition;
		}
		PointerEventData val = new PointerEventData(EventSystem.current)
		{
			position = Vector2.op_Implicit(lastMousePos)
		};
		List<RaycastResult> list = new List<RaycastResult>();
		EventSystem.current.RaycastAll(val, list);
		foreach (RaycastResult item in list)
		{
			RaycastResult current = item;
			if (((RaycastResult)(ref current)).gameObject.layer != LayerMask.NameToLayer("UI"))
			{
				continue;
			}
			if (((Object)((RaycastResult)(ref current)).gameObject).name == "Craft")
			{
				flag = true;
				if (tabCraftPressed == 0)
				{
					if (useScrollWheel.Value && AedenthornUtils.CheckKeyHeld(scrollModKey.Value, req: false) && Input.mouseScrollDelta.y != 0f)
					{
						SwitchFilter(Input.mouseScrollDelta.y < 0f);
					}
					if (showMenu.Value)
					{
						UpdateDropDown(show: true);
					}
				}
			}
			else if (dropDownList.Contains(((RaycastResult)(ref current)).gameObject))
			{
				flag = true;
			}
		}
		if (!flag)
		{
			if (tabCraftPressed > 0)
			{
				tabCraftPressed--;
			}
			UpdateDropDown(show: false);
		}
		if (AedenthornUtils.CheckKeyDown(prevHotKey.Value))
		{
			SwitchFilter(next: false);
		}
		else if (AedenthornUtils.CheckKeyDown(nextHotKey.Value))
		{
			SwitchFilter(next: true);
		}
		lastMousePos = Input.mousePosition;
	}

	private static void SwitchFilter(int idx)
	{
		lastCategoryIndex = idx;
		UpdateDropDown(show: false);
		SwitchFilter();
	}

	private static void SwitchFilter(bool next)
	{
		if (next)
		{
			lastCategoryIndex++;
			lastCategoryIndex %= categoryNames.Count;
		}
		else
		{
			lastCategoryIndex--;
			if (lastCategoryIndex < 0)
			{
				lastCategoryIndex = categoryNames.Count - 1;
			}
		}
		List<Recipe> list = new List<Recipe>();
		Player.m_localPlayer.GetAvailableRecipes(ref list);
		int num = 0;
		while (!categoryDict[categoryNames[lastCategoryIndex]].Contains((ItemType)0) && list.FindAll((Recipe r) => categoryDict[categoryNames[lastCategoryIndex]].Contains(r.m_item.m_itemData.m_shared.m_itemType)).Count == 0 && num < categoryNames.Count)
		{
			num++;
			if (next)
			{
				lastCategoryIndex++;
				lastCategoryIndex %= categoryNames.Count;
				continue;
			}
			lastCategoryIndex--;
			if (lastCategoryIndex < 0)
			{
				lastCategoryIndex = categoryNames.Count - 1;
			}
		}
		SwitchFilter();
	}

	private static void SwitchFilter()
	{
		List<Recipe> list = new List<Recipe>();
		Player.m_localPlayer.GetAvailableRecipes(ref list);
		Dbgl($"Switching to filter {categoryNames[lastCategoryIndex]} {list.Count} total recipes ");
		Traverse val = Traverse.Create((object)InventoryGui.instance);
		val.Method("UpdateRecipeList", new object[1] { list }).GetValue();
		val.Method("SetRecipe", new object[2] { 0, true }).GetValue();
		((Component)InventoryGui.instance.m_tabCraft).gameObject.GetComponentInChildren<TMP_Text>().text = Localization.instance.Localize("$inventory_craftbutton") + (categoryDict[categoryNames[lastCategoryIndex]].Contains((ItemType)0) ? "" : ("\n" + categoryNames[lastCategoryIndex]));
	}

	private static void GetFilteredRecipes(ref List<Recipe> recipes)
	{
		if (InventoryGui.instance.InCraftTab() && !categoryDict[categoryNames[lastCategoryIndex]].Contains((ItemType)0))
		{
			recipes = recipes.FindAll((Recipe r) => categoryDict[categoryNames[lastCategoryIndex]].Contains(r.m_item.m_itemData.m_shared.m_itemType));
			Dbgl($"using filter {categoryNames[lastCategoryIndex]}, {recipes.Count} filtered recipes");
		}
	}

	private static void UpdateDropDown(bool show)
	{
		//IL_005c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: 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_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		if (show == isShowing)
		{
			return;
		}
		if (show)
		{
			List<Recipe> list = new List<Recipe>();
			Player.m_localPlayer.GetAvailableRecipes(ref list);
			float scaleFactor = GameObject.Find("LoadingGUI").GetComponent<CanvasScaler>().scaleFactor;
			Vector2 val = Vector2.op_Implicit(((Transform)((Component)((Component)InventoryGui.instance.m_tabCraft).gameObject.transform).GetComponent<RectTransform>()).position);
			Rect rect = ((Component)((Component)InventoryGui.instance.m_tabCraft).gameObject.transform).GetComponent<RectTransform>().rect;
			float num = ((Rect)(ref rect)).height * scaleFactor;
			int num2 = 0;
			int i;
			for (i = 0; i < categoryNames.Count; i++)
			{
				int count = list.FindAll((Recipe r) => categoryDict[categoryNames[i]].Contains(r.m_item.m_itemData.m_shared.m_itemType)).Count;
				dropDownList[i].SetActive(count > 0 || categoryDict[categoryNames[i]].Contains((ItemType)0));
				if (count > 0 || categoryDict[categoryNames[i]].Contains((ItemType)0))
				{
					((Transform)dropDownList[i].GetComponent<RectTransform>()).position = Vector2.op_Implicit(val - new Vector2(0f, num * (float)(num2++ + 1)));
					dropDownList[i].GetComponentInChildren<TMP_Text>().text = categoryNames[i] + ((count == 0) ? "" : $" ({count})");
				}
			}
		}
		else
		{
			for (int j = 0; j < categoryNames.Count; j++)
			{
				dropDownList[j].SetActive(false);
			}
		}
		isShowing = show;
	}
}
public class CategoryData
{
	public List<string> categories = new List<string>();

	public CategoryData()
	{
		string[] names = Enum.GetNames(typeof(ItemType));
		foreach (string text in names)
		{
			categories.Add(text + ":" + text);
		}
	}
}