Please disclose if any significant portion of your mod was created 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 HammerCraftingMaterials v1.1.0
plugins/HammerCraftingMaterials.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.EventSystems; [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: AssemblyCompany("HammerCraftingMaterials")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("Right-click any piece in the hammer build menu to pull its required materials from nearby chests directly into your inventory.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+c65c3abdffb53e6aca80026cce920f159a7f833d")] [assembly: AssemblyProduct("HammerCraftingMaterials")] [assembly: AssemblyTitle("HammerCraftingMaterials")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.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 HammerCraftingMaterials { [BepInPlugin("com.hammercraftingmaterials.valheim", "HammerCraftingMaterials", "1.1.0")] [BepInProcess("valheim.exe")] [BepInProcess("Valheim.app")] public class HammerCraftingMaterialsPlugin : BaseUnityPlugin { public const string PluginGUID = "com.hammercraftingmaterials.valheim"; public const string PluginName = "HammerCraftingMaterials"; public const string PluginVersion = "1.1.0"; internal static ManualLogSource Log; internal static ConfigEntry<float> ChestSearchRadius; private readonly Harmony _harmony = new Harmony("com.hammercraftingmaterials.valheim"); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; ChestSearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChestSearchRadius", 10f, "How far (meters) to search for nearby chests when pulling materials."); _harmony.PatchAll(Assembly.GetExecutingAssembly()); Log.LogInfo((object)string.Format("{0} v{1} loaded! Search radius: {2}m", "HammerCraftingMaterials", "1.1.0", ChestSearchRadius.Value)); } private void Update() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetMouseButtonDown(1)) { return; } Hud instance = Hud.instance; if ((Object)(object)instance == (Object)null) { return; } GameObject value = Traverse.Create((object)instance).Field("m_pieceSelectionWindow").GetValue<GameObject>(); if ((Object)(object)value == (Object)null || !value.activeSelf) { return; } bool forcePull = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); PointerEventData val = new PointerEventData(EventSystem.current) { position = Vector2.op_Implicit(Input.mousePosition) }; List<RaycastResult> list = new List<RaycastResult>(); EventSystem current = EventSystem.current; if (current != null) { current.RaycastAll(val, list); } foreach (RaycastResult item in list) { RaycastResult current2 = item; PieceIconReference componentInParent = ((RaycastResult)(ref current2)).gameObject.GetComponentInParent<PieceIconReference>(); if ((Object)(object)componentInParent?.Piece == (Object)null) { continue; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { continue; } string text = PullLogic.PullMaterialsForPiece(componentInParent.Piece, localPlayer, forcePull); Log.LogInfo((object)("[HCM] " + text)); MessageHud instance2 = MessageHud.instance; if (instance2 != null) { instance2.ShowMessage((MessageType)1, text, 0, (Sprite)null, false); } break; } } private void OnDestroy() { _harmony.UnpatchSelf(); } } public class PieceIconReference : MonoBehaviour { public Piece Piece = null; } public static class PullLogic { public static List<Container> GetNearbyContainers(Vector3 origin, float radius) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) List<Container> list = new List<Container>(); Collider[] array = Physics.OverlapSphere(origin, radius); Collider[] array2 = array; foreach (Collider val in array2) { Container componentInParent = ((Component)val).GetComponentInParent<Container>(); if (!((Object)(object)componentInParent == (Object)null) && !list.Contains(componentInParent) && !((Object)(object)((Component)componentInParent).GetComponent<Player>() != (Object)null) && Traverse.Create((object)componentInParent).Method("CheckAccess", new object[1] { Game.instance.GetPlayerProfile().GetPlayerID() }).GetValue<bool>()) { list.Add(componentInParent); } } return list; } public static string PullMaterialsForPiece(Piece piece, Player player, bool forcePull = false) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece == (Object)null) { return "No piece selected."; } if (piece.m_resources == null || piece.m_resources.Length == 0) { return Localization.instance.Localize(piece.m_name) + " has no material requirements."; } List<Container> nearbyContainers = GetNearbyContainers(((Component)player).transform.position, HammerCraftingMaterialsPlugin.ChestSearchRadius.Value); if (nearbyContainers.Count == 0) { return "No accessible chests found nearby."; } Dictionary<string, int> dictionary = new Dictionary<string, int>(); Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (!((Object)(object)val.m_resItem == (Object)null)) { string name = val.m_resItem.m_itemData.m_shared.m_name; int num = ((Humanoid)player).GetInventory().CountItems(name, -1, true); int num2 = val.m_amount - num; if (num2 > 0 || forcePull) { dictionary[name] = (forcePull ? val.m_amount : num2); } } } if (dictionary.Count == 0) { return "You already have all required materials!"; } Dictionary<string, int> dictionary2 = new Dictionary<string, int>(); Inventory inventory = ((Humanoid)player).GetInventory(); foreach (Container item in nearbyContainers) { if (dictionary.Count == 0) { break; } Inventory inventory2 = item.GetInventory(); bool flag = false; foreach (KeyValuePair<string, int> item2 in dictionary.ToList()) { string itemName = item2.Key; int value = item2.Value; int num3 = inventory2.CountItems(itemName, -1, true); if (num3 <= 0) { continue; } int num4 = Mathf.Min(num3, value); ItemData val2 = ((IEnumerable<ItemData>)inventory2.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => i.m_shared.m_name == itemName)); if (val2 == null || (!inventory.HaveEmptySlot() && inventory.FindFreeStackSpace(itemName, 1f) <= 0)) { continue; } inventory2.RemoveItem(itemName, num4, -1, true); flag = true; string text = (((Object)(object)val2.m_dropPrefab != (Object)null) ? ((Object)val2.m_dropPrefab).name : val2.m_shared.m_name); if (inventory.AddItem(text, num4, val2.m_quality, val2.m_variant, player.GetPlayerID(), player.GetPlayerName(), false) != null) { dictionary2.TryGetValue(itemName, out var value2); dictionary2[itemName] = value2 + num4; dictionary[itemName] -= num4; if (dictionary[itemName] <= 0) { dictionary.Remove(itemName); } } else { inventory2.AddItem(text, num4, val2.m_quality, val2.m_variant, 0L, "", false); } } if (flag) { Traverse.Create((object)item).Method("Save", Array.Empty<object>()).GetValue(); } } if (dictionary2.Count == 0) { return "None of the required materials were found in nearby chests."; } string text2 = string.Join(", ", dictionary2.Select((KeyValuePair<string, int> kvp) => $"{kvp.Value}x {Localization.instance.Localize(kvp.Key)}")); if (dictionary.Count == 0) { return forcePull ? ("Force pulled: " + text2) : ("Pulled: " + text2); } string text3 = string.Join(", ", dictionary.Select((KeyValuePair<string, int> kvp) => $"{kvp.Value}x {Localization.instance.Localize(kvp.Key)}")); return "Pulled: " + text2 + " | Still missing: " + text3; } } [HarmonyPatch(typeof(Hud), "UpdatePieceList")] public static class Hud_UpdatePieceList_Patch { private static readonly FieldInfo? _pieceIconsField = typeof(Hud).GetField("m_pieceIcons", BindingFlags.Instance | BindingFlags.NonPublic); private static FieldInfo? _goField; [HarmonyPostfix] private static void Postfix(Hud __instance) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } PieceTable value = Traverse.Create((object)localPlayer).Field("m_buildPieces").GetValue<PieceTable>(); if ((Object)(object)value == (Object)null) { return; } List<Piece> piecesInSelectedCategory = value.GetPiecesInSelectedCategory(); if (piecesInSelectedCategory == null || piecesInSelectedCategory.Count == 0) { return; } if (!(_pieceIconsField?.GetValue(__instance) is IList list)) { HammerCraftingMaterialsPlugin.Log.LogWarning((object)"[HCM] m_pieceIcons field not found on Hud"); return; } for (int i = 0; i < list.Count && i < piecesInSelectedCategory.Count; i++) { object obj = list[i]; if (obj == null) { continue; } if (_goField == null) { _goField = obj.GetType().GetField("m_go", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } object? obj2 = _goField?.GetValue(obj); GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null); if (val != null) { Piece val2 = piecesInSelectedCategory[i]; if (!((Object)(object)val2 == (Object)null)) { PieceIconReference pieceIconReference = val.GetComponent<PieceIconReference>() ?? val.AddComponent<PieceIconReference>(); pieceIconReference.Piece = val2; } } } } } }