Decompiled source of MultiCraft v1.3.0

MultiCraft.dll

Decompiled a year 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 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: AssemblyVersion("0.0.0.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_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();
		}
	}
}
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.3.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.3.0";

	public static ConfigEntry<bool> CapMaximumCrafts;

	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.");
		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 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 = value;
	}

	public void AddToCraftAmount(int delta)
	{
		CurrentCraftAmount += delta;
		if (MultiCraftPlugin.CapMaximumCrafts.Value)
		{
			CurrentCraftAmount = Math.Min(CurrentCraftAmount, CurrentRecipeInformation.instance.GetCurrentMaxCraftable());
		}
		if (CurrentCraftAmount < 1)
		{
			CurrentCraftAmount = 1;
		}
	}

	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";
	}

	private static MultiCraft_UI _instance;

	public static bool Started;

	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_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: Expected O, but got Unknown
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Expected O, but got Unknown
		//IL_0173: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Expected O, but got Unknown
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Expected O, but got Unknown
		//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: 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, "+");
			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, "-");
			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));
		}
		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()
	{
		if ((Object)(object)plusButton != (Object)null && (Object)(object)((Component)plusButton).GetComponent<Button>() != (Object)null)
		{
			((Behaviour)((Component)plusButton).GetComponent<Button>()).enabled = false;
		}
		if ((Object)(object)minusButton != (Object)null && (Object)(object)((Component)minusButton).GetComponent<Button>() != (Object)null)
		{
			((Behaviour)((Component)minusButton).GetComponent<Button>()).enabled = false;
		}
	}

	public void UnblockCustomButtons()
	{
		if ((Object)(object)plusButton != (Object)null && (Object)(object)((Component)plusButton).GetComponent<Button>() != (Object)null)
		{
			((Behaviour)((Component)plusButton).GetComponent<Button>()).enabled = true;
		}
		if ((Object)(object)minusButton != (Object)null && (Object)(object)((Component)minusButton).GetComponent<Button>() != (Object)null)
		{
			((Behaviour)((Component)minusButton).GetComponent<Button>()).enabled = true;
		}
	}

	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()
	{
		int delta = 1;
		if (Input.GetKey((KeyCode)306))
		{
			delta = 99;
		}
		else if (Input.GetKey((KeyCode)304))
		{
			delta = 10;
		}
		MultiCraft_Logic.instance.AddToCraftAmount(delta);
	}

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

	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)
	{
		//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;
		}
		return val;
	}
}
public class RequirementInformation
{
	public string name;

	public int RequiredAmount;

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

	public int GetMaxByCurrentRequirement()
	{
		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();
			}
		}
	}

	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;
	}
}
[HarmonyPatch(typeof(InventoryGui), "SetupRequirement", new Type[]
{
	typeof(Transform),
	typeof(Requirement),
	typeof(Player),
	typeof(bool),
	typeof(int)
})]
public static class SetupRequirement_Patch
{
	private static void Postfix(Transform elementRoot, Requirement req, Player player, bool craft, int quality)
	{
		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}";
	}
}