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