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 StashLink v1.0.0
StashLink.dll
Decompiled 5 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("StashLink")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("StashLink")] [assembly: AssemblyTitle("StashLink")] [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 StashLink { public static class ChestFinder { private const float CacheSeconds = 0.5f; private static List<Container> cache = new List<Container>(); private static Vector3 cacheCenter; private static float cacheRadius; private static float cacheTime = -999f; private static readonly Dictionary<string, int> totals = new Dictionary<string, int>(); private static readonly HashSet<string> seenNames = new HashSet<string>(); private static bool totalsDirty = true; private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); private static readonly MethodInfo WardCheckMethod = typeof(PrivateArea).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => m.Name == "CheckAccess" && m.GetParameters().Length >= 1 && m.GetParameters()[0].ParameterType == typeof(Vector3)); public static bool AccessCheckAvailable { get { if (CheckAccessMethod != null) { return WardCheckMethod != null; } return false; } } private static bool HasAccess(Container container, long playerId) { if (CheckAccessMethod == null) { return false; } return (bool)CheckAccessMethod.Invoke(container, new object[1] { playerId }); } private static bool WardAllows(Vector3 position) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (WardCheckMethod == null) { return false; } ParameterInfo[] parameters = WardCheckMethod.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; if (i == 0) { array[i] = position; } else if (parameterInfo.Name == "flash") { array[i] = false; } else if (parameterInfo.HasDefaultValue) { array[i] = parameterInfo.DefaultValue; } else { array[i] = (parameterInfo.ParameterType.IsValueType ? Activator.CreateInstance(parameterInfo.ParameterType) : null); } } return (bool)WardCheckMethod.Invoke(null, array); } public static bool TryGetContext(Player player, out Vector3 center, out float radius) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) CraftingStation currentCraftingStation = player.GetCurrentCraftingStation(); if ((Object)(object)currentCraftingStation != (Object)null) { center = ((Component)currentCraftingStation).transform.position; radius = StashLinkPlugin.Radius.Value; return true; } if (((Character)player).InPlaceMode()) { center = ((Component)player).transform.position; radius = StashLinkPlugin.BuildRadius.Value; return true; } center = Vector3.zero; radius = 0f; return false; } public static List<Container> GetNearbyContainers(Vector3 center, float radius, bool fresh = false) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) if (!fresh && Time.time - cacheTime < 0.5f) { Vector3 val = center - cacheCenter; if (((Vector3)(ref val)).sqrMagnitude < 1f && radius == cacheRadius) { return cache; } } List<Container> list = new List<Container>(); Collider[] array = Physics.OverlapSphere(center, radius); Player localPlayer = Player.m_localPlayer; Collider[] array2 = array; for (int i = 0; i < array2.Length; i++) { Container componentInParent = ((Component)array2[i]).GetComponentInParent<Container>(); if (!((Object)(object)componentInParent == (Object)null) && !list.Contains(componentInParent) && componentInParent.GetInventory() != null && !((Object)(object)localPlayer == (Object)null) && HasAccess(componentInParent, localPlayer.GetPlayerID()) && WardAllows(((Component)componentInParent).transform.position)) { list.Add(componentInParent); } } cache = list; cacheCenter = center; cacheRadius = radius; cacheTime = Time.time; totalsDirty = true; return list; } public static int CountInChests(string name, Vector3 center, float radius) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) List<Container> nearbyContainers = GetNearbyContainers(center, radius); if (totalsDirty) { totals.Clear(); foreach (Container item in nearbyContainers) { if ((Object)(object)item == (Object)null) { continue; } Inventory inventory = item.GetInventory(); seenNames.Clear(); foreach (ItemData allItem in inventory.GetAllItems()) { string name2 = allItem.m_shared.m_name; if (seenNames.Add(name2)) { totals.TryGetValue(name2, out var value); totals[name2] = value + inventory.CountItems(name2, -1, true); } } } totalsDirty = false; } if (!totals.TryGetValue(name, out var value2)) { return 0; } return value2; } public static void InvalidateCounts() { totalsDirty = true; } } [HarmonyPatch(typeof(Inventory), "CountItems")] public static class CountItemsPatch { private static void Postfix(Inventory __instance, string name, ref int __result) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (StashLinkPlugin.IgnoreChests) { return; } try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && __instance == ((Humanoid)localPlayer).GetInventory() && ChestFinder.TryGetContext(localPlayer, out var center, out var radius)) { __result += ChestFinder.CountInChests(name, center, radius); } } catch (Exception ex) { StashLinkPlugin.Log.LogError((object)ex); } } } [HarmonyPatch] public static class RemoveItemPatch { private static MethodBase TargetMethod() { return AccessTools.GetDeclaredMethods(typeof(Inventory)).First((MethodInfo m) => m.Name == "RemoveItem" && m.GetParameters().Length >= 2 && m.GetParameters()[0].ParameterType == typeof(string) && m.GetParameters()[1].ParameterType == typeof(int)); } private static void Prefix(Inventory __instance, string name, ref int amount) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || __instance != ((Humanoid)localPlayer).GetInventory() || !ChestFinder.TryGetContext(localPlayer, out var center, out var radius)) { return; } StashLinkPlugin.IgnoreChests = true; int num; try { num = __instance.CountItems(name, -1, true); } finally { StashLinkPlugin.IgnoreChests = false; } int num2 = amount - num; if (num2 <= 0) { return; } foreach (Container nearbyContainer in ChestFinder.GetNearbyContainers(center, radius, fresh: true)) { if (num2 <= 0) { break; } if (!((Object)(object)nearbyContainer == (Object)null)) { Inventory inventory = nearbyContainer.GetInventory(); int num3 = Math.Min(num2, inventory.CountItems(name, -1, true)); if (num3 > 0) { inventory.RemoveItem(name, num3, -1, true); num2 -= num3; } } } ChestFinder.InvalidateCounts(); amount = num + num2; } catch (Exception ex) { StashLinkPlugin.Log.LogError((object)ex); } } } [BepInPlugin("rhyzt.valheim.stashlink", "StashLink", "1.0.0")] public class StashLinkPlugin : BaseUnityPlugin { public static ConfigEntry<float> Radius; public static ConfigEntry<float> BuildRadius; public static ManualLogSource Log; public static bool IgnoreChests; private void Awake() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) Radius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Radius", 10f, "Radius (in meters) around the station where chest will be searched for crafting"); Log = ((BaseUnityPlugin)this).Logger; BuildRadius = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BuildRadius", 10f, "Radius (in meters) around the player where chests will be searched for building"); ((BaseUnityPlugin)this).Logger.LogError((object)"Game access checks not found: the mod will not use any chests."); new Harmony("rhyzt.valheim.stashlink").PatchAll(); } } }