Decompiled source of MultiCraft v1.5.0

MultiCraft.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CraftFromContainers;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MultiCraft")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MultiCraft")]
[assembly: AssemblyTitle("MultiCraft")]
[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 MultiCraft
{
	[HarmonyPatch(typeof(InventoryGui), "Show")]
	public static class CraftGUI_Patch
	{
		private static void Postfix(Container container)
		{
			MultiCraft_UI.instance?.Start();
			MultiCraft_Logic.instance?.Start();
		}

		public static void Update()
		{
			if (MultiCraft_Logic.Started && InventoryGui.IsVisible())
			{
				MultiCraft_UI.instance.RefreshCustomButtonStates();
				MultiCraft_Logic.instance.Update();
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Hide")]
	public static class CraftGUI_Hide_Patch
	{
		private static void Postfix()
		{
			if (MultiCraft_Logic.Started)
			{
				MultiCraft_Logic.instance.ResetMultiCrafting();
			}
		}
	}
	public class RequirementInformation
	{
		public string name;

		public int RequiredAmount;

		public RequirementInformation(int reqAmount, string itemName)
		{
			RequiredAmount = reqAmount;
			name = itemName;
		}

		public int GetMaxByCurrentRequirement()
		{
			if (RequiredAmount <= 0)
			{
				return int.MaxValue;
			}
			return Helper.GetAvailableItems(name) / RequiredAmount;
		}
	}
	public class CurrentRecipeInformation
	{
		private static CurrentRecipeInformation _instance;

		public static UnityEvent OnRecipeChanged = new UnityEvent();

		private Dictionary<string, RequirementInformation> requirements;

		private string _name = "";

		public static CurrentRecipeInformation instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new CurrentRecipeInformation();
				}
				return _instance;
			}
		}

		public static bool Started { get; private set; }

		public bool IsRecipeReady { get; private set; }

		public string name
		{
			get
			{
				return _name;
			}
			set
			{
				if (!IsRecipe(value))
				{
					_name = value;
					UnityEvent onRecipeChanged = OnRecipeChanged;
					if (onRecipeChanged != null)
					{
						onRecipeChanged.Invoke();
					}
					ClearRequirements();
				}
			}
		}

		public bool HasRequirements => requirements.Count > 0;

		private CurrentRecipeInformation()
		{
			requirements = new Dictionary<string, RequirementInformation>();
			IsRecipeReady = false;
		}

		public void Start()
		{
			Started = true;
		}

		public bool IsRecipe(string otherName)
		{
			return name == otherName;
		}

		public void ClearRequirements()
		{
			IsRecipeReady = false;
			requirements.Clear();
		}

		public void AddRequirement(string name, int requiredAmount)
		{
			if (requirements.ContainsKey(name))
			{
				IsRecipeReady = true;
				return;
			}
			RequirementInformation value = new RequirementInformation(requiredAmount, name);
			requirements[name] = value;
		}

		public int GetCurrentMaxCraftable()
		{
			int num = 99;
			foreach (KeyValuePair<string, RequirementInformation> requirement in requirements)
			{
				num = Math.Min(num, requirement.Value.GetMaxByCurrentRequirement());
			}
			return num;
		}
	}
	internal class Helper
	{
		public static ManualLogSource Logger;

		public static bool CraftFromContainersRunning = false;

		private static string CraftFromContainersGUID = "aedenthorn.CraftFromContainers";

		public static bool CraftFromContainersInstalledAndActive { get; private set; }

		public static void CheckAvailabilityForCraftFromContainersPlugin()
		{
			CraftFromContainersRunning = false;
			BaseUnityPlugin[] componentsInChildren = GameObject.Find("BepInEx_Manager").GetComponentsInChildren<BaseUnityPlugin>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].Info.Metadata.GUID == CraftFromContainersGUID)
				{
					CraftFromContainersRunning = IsCraftFromContainersEnabled();
				}
			}
		}

		public static bool IsCraftFromContainersEnabled()
		{
			GameObject val = GameObject.Find("BepInEx_Manager");
			Debug.Log((object)("Found bepInExManager: " + (object)val));
			BaseUnityPlugin[] componentsInChildren = val.GetComponentsInChildren<BaseUnityPlugin>();
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (componentsInChildren[i].Info.Metadata.GUID == "aedenthorn.CraftFromContainers")
				{
					return BepInExPlugin.modEnabled.Value;
				}
			}
			return false;
		}

		public static int GetAvailableItems(string itemName)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return 0;
			}
			int num = 0;
			if (CraftFromContainersRunning)
			{
				num = GetItemsInCloseContainers(itemName);
			}
			return ((Humanoid)localPlayer).GetInventory().CountItems(itemName, -1, true) + num;
		}

		public static int GetItemsInCloseContainers(string itemName)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (CraftFromContainersRunning)
			{
				int num = 0;
				{
					foreach (Container nearbyContainer in BepInExPlugin.GetNearbyContainers(((Component)Player.m_localPlayer).transform.position))
					{
						num += nearbyContainer.GetInventory().CountItems(itemName, -1, true);
					}
					return num;
				}
			}
			return ((Humanoid)Player.m_localPlayer).GetInventory().CountItems(itemName, -1, true);
		}
	}
	[HarmonyPatch(typeof(Menu), "Start", new Type[] { })]
	public static class MainMenuShow_Patch
	{
		private static void Postfix()
		{
			Helper.CheckAvailabilityForCraftFromContainersPlugin();
		}
	}
	[BepInPlugin("maximods.valheim.multicraft", "MultiCraft", "1.5.0")]
	[BepInProcess("valheim.exe")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class MultiCraftPlugin : BaseUnityPlugin
	{
		public const string pluginGuid = "maximods.valheim.multicraft";

		public const string pluginName = "MultiCraft";

		public const string pluginVersion = "1.5.0";

		public static ConfigEntry<bool> CapMaximumCrafts;

		public static ConfigEntry<bool> DisableVanillaMultiCraft;

		public static ConfigEntry<bool> GreyOutPlusAtMax;

		public static ConfigEntry<bool> EnableGamepadInput;

		public static ConfigEntry<int> GamepadBulkStep;

		public static ConfigEntry<bool> ShowCraftAmountHints;

		private Harmony _harmony;

		public static bool CraftFromContainersInstalledAndActive;

		private static List<Container> cachedContainers;

		public void Awake()
		{
			CapMaximumCrafts = ((BaseUnityPlugin)this).Config.Bind<bool>("MultiCraft", "CapMaximumCrafts", false, "Caps the maximum amount to craft to the maximum possible to craft.");
			DisableVanillaMultiCraft = ((BaseUnityPlugin)this).Config.Bind<bool>("Compatibility", "DisableVanillaMultiCraft", true, "Disables Valheim's built-in \"Craft x5\" shortcut (Left Shift on keyboard, Left Stick click on controller) while MultiCraft is active, including the \" x 5\" suffix on the craft button.");
			GreyOutPlusAtMax = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "GreyOutPlusAtMax", true, "Greys out the + button once the craft amount reaches the maximum craftable with the materials available.");
			EnableGamepadInput = ((BaseUnityPlugin)this).Config.Bind<bool>("Gamepad", "EnableGamepadInput", true, "Enables controller input for the craft amount. D-Pad Left/Right steps the amount; hold Left Trigger for bulk steps, hold Right Trigger to jump to the maximum (or back to 1).");
			GamepadBulkStep = ((BaseUnityPlugin)this).Config.Bind<int>("Gamepad", "GamepadBulkStep", 10, "How much the amount changes when Left Trigger is held while pressing D-Pad Left/Right.");
			ShowCraftAmountHints = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowCraftAmountHints", true, "Adds entries to the inventory hint bar describing the bulk and maximum craft-amount shortcuts.");
			Helper.Logger = ((BaseUnityPlugin)this).Logger;
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
		}

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

		private void Update()
		{
			CraftGUI_Patch.Update();
		}

		private void LateUpdate()
		{
			if (CraftFromContainersInstalledAndActive && cachedContainers != null)
			{
				cachedContainers.Clear();
				cachedContainers = null;
			}
		}
	}
	public static class MultiCraft_KeyHints
	{
		private const string BULK_ENTRY = "MultiCraft_Bulk";

		private const string MAX_ENTRY = "MultiCraft_Max";

		private const string KEYBOARD_GROUP = "Keyboard";

		private const string KEYBOARD_TEMPLATE = "Split";

		private const string GAMEPAD_TEMPLATE = "Text - Split";

		private static readonly string[] HintRoots = new string[2] { "InventoryHints", "InventoryWithContainerHints" };

		private static readonly string[] GamepadGroups = new string[2] { "Gamepad", "GamepadMouse" };

		private static readonly string[] VanillaMultiCraftEntries = new string[3] { "Keyboard/Multicraft", "Gamepad/Text - Multicraft", "GamepadMouse/Text - Multicraft" };

		public static void Refresh()
		{
			if ((Object)(object)KeyHints.instance == (Object)null)
			{
				return;
			}
			string[] hintRoots = HintRoots;
			foreach (string text in hintRoots)
			{
				Transform val = ((Component)KeyHints.instance).transform.Find(text);
				if (!((Object)(object)val == (Object)null))
				{
					HideVanillaMultiCraftHint(val);
					RefreshCraftAmountHints(val);
				}
			}
		}

		private static void HideVanillaMultiCraftHint(Transform root)
		{
			bool active = !MultiCraftPlugin.DisableVanillaMultiCraft.Value;
			string[] vanillaMultiCraftEntries = VanillaMultiCraftEntries;
			foreach (string text in vanillaMultiCraftEntries)
			{
				Transform val = root.Find(text);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(active);
				}
			}
		}

		private static void RefreshCraftAmountHints(Transform root)
		{
			bool value = MultiCraftPlugin.ShowCraftAmountHints.Value;
			int num = Mathf.Max(1, MultiCraftPlugin.GamepadBulkStep.Value);
			Transform val = root.Find("Keyboard");
			if ((Object)(object)val != (Object)null)
			{
				Transform orCreateEntry = GetOrCreateEntry(val, "Split", "MultiCraft_Bulk");
				SetKeyboardEntry(orCreateEntry, "Craft +" + num, "L-Shift");
				Transform orCreateEntry2 = GetOrCreateEntry(val, "Split", "MultiCraft_Max");
				SetKeyboardEntry(orCreateEntry2, "Craft max", "L-Ctrl");
				SetVisible(orCreateEntry, value);
				SetVisible(orCreateEntry2, value);
			}
			string[] gamepadGroups = GamepadGroups;
			foreach (string text in gamepadGroups)
			{
				Transform val2 = root.Find(text);
				if (!((Object)(object)val2 == (Object)null))
				{
					Transform orCreateEntry3 = GetOrCreateEntry(val2, "Text - Split", "MultiCraft_Bulk");
					SetGamepadEntry(orCreateEntry3, "Craft +" + num, "JoyLTrigger");
					Transform orCreateEntry4 = GetOrCreateEntry(val2, "Text - Split", "MultiCraft_Max");
					SetGamepadEntry(orCreateEntry4, "Craft max", "JoyRTrigger");
					bool visible = value && MultiCraftPlugin.EnableGamepadInput.Value;
					SetVisible(orCreateEntry3, visible);
					SetVisible(orCreateEntry4, visible);
				}
			}
		}

		private static Transform GetOrCreateEntry(Transform group, string templateName, string entryName)
		{
			Transform val = group.Find(entryName);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Transform val2 = group.Find(templateName);
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Transform obj = Object.Instantiate<Transform>(val2, group);
			((Object)obj).name = entryName;
			obj.SetAsLastSibling();
			return obj;
		}

		private static void SetKeyboardEntry(Transform entry, string label, string modifierKey)
		{
			if (!((Object)(object)entry == (Object)null))
			{
				SetText(entry.Find("Text"), label);
				SetText(entry.Find("key_bkg/Key"), modifierKey);
				SetText(entry.Find("key_bkg (2)/Key"), "Mouse-1");
			}
		}

		private static void SetGamepadEntry(Transform entry, string label, string modifierZinputKey)
		{
			if (!((Object)(object)entry == (Object)null) && ZInput.instance != null)
			{
				string boundKeyString = ZInput.instance.GetBoundKeyString(modifierZinputKey, true);
				string boundKeyString2 = ZInput.instance.GetBoundKeyString("JoyDPadRight", true);
				if (!string.IsNullOrEmpty(boundKeyString) && !string.IsNullOrEmpty(boundKeyString2))
				{
					SetText(entry, label + " <mspace=0.6em> " + boundKeyString + " + " + boundKeyString2 + "</mspace>");
				}
			}
		}

		private static void SetText(Transform target, string value)
		{
			if (!((Object)(object)target == (Object)null))
			{
				TMP_Text component = ((Component)target).GetComponent<TMP_Text>();
				if ((Object)(object)component != (Object)null)
				{
					component.text = value;
				}
			}
		}

		private static void SetVisible(Transform entry, bool visible)
		{
			if ((Object)(object)entry != (Object)null)
			{
				((Component)entry).gameObject.SetActive(visible);
			}
		}
	}
	public class MultiCraft_Logic
	{
		private static MultiCraft_Logic _instance;

		public static bool Started;

		private int _CurrentCraftAmount = 1;

		public int value = 5;

		private bool WasCrafting;

		private int WaitUpdates;

		public static MultiCraft_Logic instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new MultiCraft_Logic();
				}
				return _instance;
			}
		}

		public int CurrentCraftAmount
		{
			get
			{
				return _CurrentCraftAmount;
			}
			set
			{
				_CurrentCraftAmount = value;
				MultiCraft_UI.instance.UpdateAmountLabel(_CurrentCraftAmount);
			}
		}

		public void Start()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Expected O, but got Unknown
			Started = true;
			CurrentCraftAmount = 1;
			CurrentRecipeInformation.OnRecipeChanged.AddListener(new UnityAction(OnRecipeChanged));
		}

		public void OnRecipeChanged()
		{
			ResetMultiCrafting();
		}

		public void ResetMultiCrafting()
		{
			CurrentCraftAmount = 1;
			CancelMultiCrafting();
		}

		public void CancelMultiCrafting()
		{
			WasCrafting = false;
			if (Object.op_Implicit((Object)(object)InventoryGui.instance) && InventoryGui.instance.InCraftTab())
			{
				MultiCraft_UI.instance.UnblockCustomButtons();
			}
		}

		public void StartCraftingLogic()
		{
			WasCrafting = true;
			WaitUpdates = 5;
		}

		public void SetCraftAmount(int value)
		{
			CurrentCraftAmount = ClampCraftAmount(value);
		}

		public void AddToCraftAmount(int delta)
		{
			CurrentCraftAmount = ClampCraftAmount(CurrentCraftAmount + delta);
		}

		private int ClampCraftAmount(int value)
		{
			if (MultiCraftPlugin.CapMaximumCrafts.Value)
			{
				value = Math.Min(value, CurrentRecipeInformation.instance.GetCurrentMaxCraftable());
			}
			if (value < 1)
			{
				value = 1;
			}
			return value;
		}

		public bool IsCrafting()
		{
			return ((Component)InventoryGui.instance.m_craftProgressBar).gameObject.activeInHierarchy;
		}

		public void Update()
		{
			if (WaitUpdates-- <= 0 && WasCrafting && !IsCrafting())
			{
				if (CurrentCraftAmount <= 1)
				{
					CancelMultiCrafting();
				}
				else
				{
					TryNextCraft();
				}
			}
		}

		public void TryNextCraft()
		{
			WasCrafting = false;
			if (CurrentCraftAmount > 1)
			{
				int currentCraftAmount = CurrentCraftAmount - 1;
				CurrentCraftAmount = currentCraftAmount;
				if (!instance.CanCraft())
				{
					CancelMultiCrafting();
				}
				else
				{
					((UnityEvent)((Component)InventoryGui.instance.m_craftButton).GetComponent<Button>().onClick).Invoke();
				}
			}
		}

		public bool CanCraft()
		{
			return MultiCraft_UI.instance.IsCraftButtonEnabled();
		}
	}
	public class MultiCraft_UI
	{
		private class UI_Names
		{
			public static string PLUS_BUTTON = "plus";

			public static string MINUS_BUTTON = "minus";

			public static string AMOUNT_TEXT = "amountText";
		}

		public const string PLUS_ZINPUT_KEY = "JoyDPadRight";

		public const string MINUS_ZINPUT_KEY = "JoyDPadLeft";

		private const string GAMEPAD_HINT = "gamepad_hint";

		private const float HINT_GAP = 4f;

		private const int MAX_CRAFT_AMOUNT = 99;

		private static MultiCraft_UI _instance;

		public static bool Started;

		private bool customButtonsBlocked;

		private RectTransform plusButton;

		private RectTransform minusButton;

		private RectTransform amountText;

		public static MultiCraft_UI instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new MultiCraft_UI();
				}
				return _instance;
			}
		}

		public void Start()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			InventoryGui val = InventoryGui.instance;
			CreateSpaceFromCraftButton(val);
			plusButton = FindUiComponent(UI_Names.PLUS_BUTTON);
			if (!Object.op_Implicit((Object)(object)plusButton))
			{
				Helper.Logger.LogMessage((object)"Creating new plus button");
				Started = false;
				plusButton = CreateMultiCraftButton(val, UI_Names.PLUS_BUTTON, "+", "JoyDPadRight");
				AttachButtonsToRight((Transform)(object)plusButton, 0.8f);
				((UnityEvent)((Component)plusButton).GetComponent<Button>().onClick).AddListener(new UnityAction(OnPlusButtonPressed));
			}
			minusButton = FindUiComponent(UI_Names.MINUS_BUTTON);
			if (!Object.op_Implicit((Object)(object)minusButton))
			{
				Helper.Logger.LogMessage((object)"Creating new minus button");
				Started = false;
				minusButton = CreateMultiCraftButton(val, UI_Names.MINUS_BUTTON, "-", "JoyDPadLeft");
				AttachButtonsToRight((Transform)(object)minusButton, 0.1f);
				((UnityEvent)((Component)minusButton).GetComponent<Button>().onClick).AddListener(new UnityAction(OnMinusButtonPressed));
			}
			amountText = FindUiComponent(UI_Names.AMOUNT_TEXT);
			if (!Object.op_Implicit((Object)(object)amountText))
			{
				Helper.Logger.LogMessage((object)"CreatingNewAmountText");
				Started = false;
				CreateAmountLabel();
			}
			if (!Started)
			{
				((UnityEvent)val.m_craftButton.onClick).AddListener(new UnityAction(OnCraftButtonPressed));
				((UnityEvent)val.m_craftCancelButton.onClick).AddListener(new UnityAction(OnCraftCancelledButtonPressed));
				((UnityEvent)val.m_tabCraft.onClick).AddListener(new UnityAction(TabCraftPressed));
				((UnityEvent)val.m_tabUpgrade.onClick).AddListener(new UnityAction(UpgradeTabPressed));
			}
			MultiCraft_KeyHints.Refresh();
			RefreshGamepadHintGlyph(plusButton, "JoyDPadRight");
			RefreshGamepadHintGlyph(minusButton, "JoyDPadLeft");
			Started = true;
		}

		public RectTransform FindUiComponent(string name)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			return (RectTransform)((Component)((Component)InventoryGui.instance.m_craftButton).transform.parent).transform.Find(name);
		}

		public void TabCraftPressed()
		{
			UnblockCustomButtons();
			ChangedTab();
		}

		public void UpgradeTabPressed()
		{
			BlockCustomButtons();
			ChangedTab();
		}

		public bool IsCraftButtonEnabled()
		{
			return ((Selectable)((Component)InventoryGui.instance.m_craftButton).GetComponent<Button>()).interactable;
		}

		public void ChangedTab()
		{
			MultiCraft_Logic.instance.ResetMultiCrafting();
		}

		public void BlockCustomButtons()
		{
			customButtonsBlocked = true;
			SetButtonInteractable(plusButton, value: false);
			SetButtonInteractable(minusButton, value: false);
		}

		public void UnblockCustomButtons()
		{
			customButtonsBlocked = false;
			RefreshCustomButtonStates();
		}

		public bool AreCustomButtonsUsable()
		{
			if (Started)
			{
				return !customButtonsBlocked;
			}
			return false;
		}

		public void RefreshCustomButtonStates()
		{
			if (!customButtonsBlocked)
			{
				SetButtonInteractable(plusButton, !IsAtMaximumCraftable());
				SetButtonInteractable(minusButton, MultiCraft_Logic.instance.CurrentCraftAmount > 1);
			}
		}

		private bool IsAtMaximumCraftable()
		{
			if (!MultiCraftPlugin.GreyOutPlusAtMax.Value)
			{
				return false;
			}
			if (!CurrentRecipeInformation.instance.HasRequirements)
			{
				return false;
			}
			return MultiCraft_Logic.instance.CurrentCraftAmount >= CurrentRecipeInformation.instance.GetCurrentMaxCraftable();
		}

		private static void SetButtonInteractable(RectTransform buttonTransform, bool value)
		{
			if (!((Object)(object)buttonTransform == (Object)null))
			{
				Button component = ((Component)buttonTransform).GetComponent<Button>();
				if (!((Object)(object)component == (Object)null))
				{
					((Selectable)component).interactable = value;
				}
			}
		}

		public void OnCraftCancelledButtonPressed()
		{
			MultiCraft_Logic.instance.CancelMultiCrafting();
		}

		public void OnCraftButtonPressed()
		{
			MultiCraft_Logic.instance.StartCraftingLogic();
			BlockCustomButtons();
		}

		public void CreateAmountLabel()
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			Transform val = ((Component)InventoryGui.instance.m_craftButton).transform.Find("Text");
			amountText = (RectTransform)((Component)Object.Instantiate<Transform>(val, ((Component)InventoryGui.instance.m_craftButton).transform.parent)).transform;
			((Object)amountText).name = UI_Names.AMOUNT_TEXT;
			((TMP_Text)((Component)amountText).GetComponent<TextMeshProUGUI>()).text = $"{MultiCraft_Logic.instance.CurrentCraftAmount}";
			amountText.SetSizeWithCurrentAnchors((Axis)0, 50f);
			amountText.SetSizeWithCurrentAnchors((Axis)1, 50f);
			amountText.pivot = new Vector2(1.15f, 0.3f);
		}

		public void OnRecipeSelected()
		{
			MultiCraft_Logic.instance.ResetMultiCrafting();
		}

		public void UpdateAmountLabel(int value)
		{
			if (Object.op_Implicit((Object)(object)amountText))
			{
				((TMP_Text)((Component)amountText).GetComponent<TextMeshProUGUI>()).text = $"{value}";
			}
		}

		private void OnPlusButtonPressed()
		{
			if (JumpToExtremeRequested())
			{
				MultiCraft_Logic.instance.SetCraftAmount(CurrentRecipeInformation.instance.HasRequirements ? CurrentRecipeInformation.instance.GetCurrentMaxCraftable() : 99);
				return;
			}
			int delta = 1;
			if (Input.GetKey((KeyCode)306))
			{
				delta = 99;
			}
			else if (BulkStepRequested())
			{
				delta = BulkStep();
			}
			MultiCraft_Logic.instance.AddToCraftAmount(delta);
		}

		private void OnMinusButtonPressed()
		{
			if (Input.GetKey((KeyCode)306) || JumpToExtremeRequested())
			{
				MultiCraft_Logic.instance.SetCraftAmount(1);
				return;
			}
			int delta = -1;
			if (BulkStepRequested())
			{
				delta = -BulkStep();
			}
			MultiCraft_Logic.instance.AddToCraftAmount(delta);
		}

		private static bool JumpToExtremeRequested()
		{
			if (MultiCraftPlugin.EnableGamepadInput.Value)
			{
				return ZInput.GetButton("JoyRTrigger");
			}
			return false;
		}

		private static bool BulkStepRequested()
		{
			if (!Input.GetKey((KeyCode)304))
			{
				if (MultiCraftPlugin.EnableGamepadInput.Value)
				{
					return ZInput.GetButton("JoyLTrigger");
				}
				return false;
			}
			return true;
		}

		private static int BulkStep()
		{
			return Math.Max(1, MultiCraftPlugin.GamepadBulkStep.Value);
		}

		private void RetargetGamepadBinding(RectTransform button, string zinputKey)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			UIGamePad component = ((Component)button).GetComponent<UIGamePad>();
			if (!((Object)(object)component == (Object)null))
			{
				component.m_zinputKey = zinputKey;
				component.m_keyCode = (KeyCode)0;
				RectTransform val = (RectTransform)((Transform)button).Find("gamepad_hint");
				if (!((Object)(object)val == (Object)null))
				{
					val.anchorMin = new Vector2(1f, 0.5f);
					val.anchorMax = new Vector2(1f, 0.5f);
					val.pivot = new Vector2(0f, 0.5f);
					val.anchoredPosition = new Vector2(4f, 0f);
					UpdateGamepadHintGlyph(val, zinputKey);
				}
			}
		}

		private void RefreshGamepadHintGlyph(RectTransform button, string zinputKey)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			if (!((Object)(object)button == (Object)null))
			{
				RectTransform val = (RectTransform)((Transform)button).Find("gamepad_hint");
				if ((Object)(object)val != (Object)null)
				{
					UpdateGamepadHintGlyph(val, zinputKey);
				}
			}
		}

		private void UpdateGamepadHintGlyph(RectTransform hint, string zinputKey)
		{
			if (ZInput.instance == null)
			{
				return;
			}
			string boundKeyString = ZInput.instance.GetBoundKeyString(zinputKey, true);
			if (!string.IsNullOrEmpty(boundKeyString))
			{
				TextMeshProUGUI[] componentsInChildren = ((Component)hint).GetComponentsInChildren<TextMeshProUGUI>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((TMP_Text)componentsInChildren[i]).text = boundKeyString;
				}
			}
		}

		private void CreateSpaceFromCraftButton(InventoryGui instance)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			RectTransform transform = (RectTransform)((Component)instance.m_craftButton).transform.parent;
			AttachButtonsToLeft((Transform)(object)transform);
		}

		private void AttachButtonsToLeft(Transform transform)
		{
			//IL_0010: 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_0021: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			transform.localScale = new Vector3(0.8f, 1f, 1f);
			RectTransform val = (RectTransform)transform;
			if (Object.op_Implicit((Object)(object)val))
			{
				val.anchorMin = new Vector2(0f, 0f);
				val.pivot = new Vector2(0f, 0.5f);
			}
		}

		private void AttachButtonsToRight(Transform transform, float verticalAllignment)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)transform;
			if (Object.op_Implicit((Object)(object)val))
			{
				val.pivot = new Vector2(1.3f, verticalAllignment);
			}
		}

		private RectTransform CreateMultiCraftButton(InventoryGui __instance, string name, string text, string zinputKey)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			Debug.Log((object)("Start of CreateButton: " + name));
			RectTransform val = (RectTransform)((Component)__instance).transform.parent.Find(name);
			if ((Object)(object)val == (Object)null)
			{
				Transform transform = ((Component)__instance.m_craftButton).transform;
				Transform obj = Object.Instantiate<Transform>(transform, ((Component)transform).transform.parent);
				((Object)obj).name = name;
				((Component)obj).transform.SetAsFirstSibling();
				val = (RectTransform)((Component)obj).transform;
				val.SetSizeWithCurrentAnchors((Axis)0, 45f);
				val.SetSizeWithCurrentAnchors((Axis)1, 30f);
				RectTransform val2 = (RectTransform)((Component)val).transform.Find("Text");
				val2.SetSizeWithCurrentAnchors((Axis)0, 45f);
				val2.SetSizeWithCurrentAnchors((Axis)1, 30f);
				((TMP_Text)((Component)val2).gameObject.GetComponent<TextMeshProUGUI>()).text = text;
				RetargetGamepadBinding(val, zinputKey);
			}
			return val;
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "SetupRequirement", new Type[]
	{
		typeof(Transform),
		typeof(Requirement),
		typeof(Player),
		typeof(bool),
		typeof(int),
		typeof(int)
	})]
	public static class SetupRequirement_Patch
	{
		private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality, int craftMultiplier = 1)
		{
			string name = req.m_resItem.m_itemData.m_shared.m_name;
			CurrentRecipeInformation.instance.name = InventoryGui.instance.m_recipeName.text;
			if (!CurrentRecipeInformation.instance.IsRecipeReady && req.m_amount != 0)
			{
				CurrentRecipeInformation.instance?.AddRequirement(name, req.GetAmount(quality));
			}
			UpdateRequirementLabels(elementRoot, req, quality);
		}

		private static void UpdateRequirementLabels(Transform elementRoot, Requirement req, int quality)
		{
			TextMeshProUGUI component = ((Component)((Component)elementRoot).transform.Find("res_amount")).GetComponent<TextMeshProUGUI>();
			int availableItems = Helper.GetAvailableItems(req.m_resItem.m_itemData.m_shared.m_name);
			int num = req.GetAmount(quality) * MultiCraft_Logic.instance.CurrentCraftAmount;
			((TMP_Text)component).text = $"{num}/{availableItems}";
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe", new Type[]
	{
		typeof(Player),
		typeof(float)
	})]
	public static class VanillaMultiCraft_Patch
	{
		private static int _originalMultiCraftAmount = -1;

		private static void Prefix(InventoryGui __instance)
		{
			if (_originalMultiCraftAmount < 0)
			{
				_originalMultiCraftAmount = __instance.m_multiCraftAmount;
			}
			__instance.m_multiCraftAmount = (MultiCraftPlugin.DisableVanillaMultiCraft.Value ? 1 : _originalMultiCraftAmount);
		}

		private static void Postfix(InventoryGui __instance)
		{
			if (MultiCraftPlugin.DisableVanillaMultiCraft.Value)
			{
				TMP_Text componentInChildren = ((Component)__instance.m_craftButton).GetComponentInChildren<TMP_Text>();
				if (!((Object)(object)componentInChildren == (Object)null) && componentInChildren.text.EndsWith(" x 1", StringComparison.Ordinal))
				{
					componentInChildren.text = componentInChildren.text.Substring(0, componentInChildren.text.Length - " x 1".Length);
				}
			}
		}
	}
}