Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of MultiCraft v1.4.2
MultiCraft.dll
Decompiled 7 months agousing 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.4.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.4.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), 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}"; } }