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 NoAutoPickup v0.1.2
NoAutoPickup.dll
Decompiled 2 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; 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(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("NoAutoPickup")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2+7b3884cc30328564314e91bb160e4939887cae56")] [assembly: AssemblyProduct("NoAutoPickup")] [assembly: AssemblyTitle("NoAutoPickup")] [assembly: AssemblyVersion("0.1.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 NoAutoPickup { internal static class DrawerApi { private static MethodInfo? _allDrawers; internal static void Init() { Type type = Type.GetType("API.ClientSideV2, kg_ItemDrawers"); if (type == null) { Plugin.Log.LogInfo((object)"kg.ItemDrawers not found; drawer zones disabled until that mod is present."); return; } _allDrawers = type.GetMethod("AllDrawers", BindingFlags.Static | BindingFlags.Public); if (_allDrawers == null) { Plugin.Log.LogWarning((object)"kg.ItemDrawers loaded but API.ClientSideV2.AllDrawers was not found."); } else { Plugin.Log.LogInfo((object)"Using kg.ItemDrawers AllDrawers API for drawer exclusion zones."); } } internal static bool AnyInRange(Vector3 origin, float range) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (_allDrawers == null) { return false; } float num = range * range; try { if (!(_allDrawers.Invoke(null, null) is IEnumerable enumerable)) { return false; } foreach (object item in enumerable) { ZNetView val = (ZNetView)((item is ZNetView) ? item : null); if (val != null && Object.op_Implicit((Object)(object)val) && val.IsValid() && Object.op_Implicit((Object)(object)((Component)val).transform)) { Vector3 val2 = ((Component)val).transform.position - origin; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } } catch (Exception ex) { if (ModConfig.DebugLogs.Value) { Plugin.Log.LogWarning((object)("ItemDrawers scan failed: " + ex.Message)); } } return false; } } internal static class ModConfig { internal static ConfigEntry<bool> Enabled = null; internal static ConfigEntry<bool> DebugLogs = null; internal static ConfigEntry<float> RangePadding = null; internal static ConfigEntry<float> VanillaFloor = null; internal static ConfigEntry<bool> FiresEnabled = null; internal static ConfigEntry<bool> OnlyIfBurning = null; internal static ConfigEntry<string> FirePrefabs = null; internal static ConfigEntry<bool> TamesEnabled = null; internal static ConfigEntry<bool> DrawersEnabled = null; private static HashSet<string> _firePrefabNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("General", "Enabled", true, "If off, auto-pickup is never suppressed."); DebugLogs = config.Bind<bool>("General", "Debug Logs", false, "Log when auto-pickup is suppressed or restored, and the active exclusion range."); VanillaFloor = config.Bind<float>("Range", "Vanilla Floor", 2f, "Valheim's default auto-pickup range. Used as the minimum in the max() of all pickup radii."); RangePadding = config.Bind<float>("Range", "Range Padding", 0f, "Extra meters added after taking the largest pickup-related range."); FiresEnabled = config.Bind<bool>("Fires", "Enabled", true, "Suppress auto-pickup near campfires and hearths so tossed fuel/food is not vacuumed."); OnlyIfBurning = config.Bind<bool>("Fires", "Only If Burning", false, "If on, only lit fires count. Off = unlit campfires and hearths still suppress auto-pickup."); FirePrefabs = config.Bind<string>("Fires", "Prefab Names", "fire_pit,hearth", "Comma-separated prefab names (Clone suffix ignored). Add bonfire here if you want it."); TamesEnabled = config.Bind<bool>("Tames", "Enabled", true, "Suppress auto-pickup near tamed animals so tossed food stays on the ground for them."); DrawersEnabled = config.Bind<bool>("Drawers", "Enabled", true, "Suppress auto-pickup near Item Drawers so tossed items can be vacuumed by drawers instead of players."); FirePrefabs.SettingChanged += delegate { RebuildFirePrefabs(); }; RebuildFirePrefabs(); } internal static bool IsWatchedFirePrefab(string prefabName) { return _firePrefabNames.Contains(prefabName); } private static void RebuildFirePrefabs() { _firePrefabNames = (from s in FirePrefabs.Value.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim() into s where s.Length > 0 select s).ToHashSet<string>(StringComparer.OrdinalIgnoreCase); } } internal static class FireplaceRegistry { private static readonly HashSet<Fireplace> Fires = new HashSet<Fireplace>(); internal static IEnumerable<Fireplace> All { get { Fires.RemoveWhere((Fireplace f) => !Object.op_Implicit((Object)(object)f)); return Fires; } } internal static void Add(Fireplace fire) { if (Object.op_Implicit((Object)(object)fire)) { Fires.Add(fire); } } internal static void Remove(Fireplace fire) { if (Object.op_Implicit((Object)(object)fire)) { Fires.Remove(fire); } } } [HarmonyPatch(typeof(Fireplace), "Awake")] internal static class FireplaceAwakePatch { private static void Postfix(Fireplace __instance) { FireplaceRegistry.Add(__instance); } } [HarmonyPatch(typeof(Player), "AutoPickup")] internal static class PlayerAutoPickupPatch { private static void Prefix(Player __instance) { try { PickupGuard.Tick(__instance); } catch (Exception arg) { Plugin.Log.LogError((object)$"NoAutoPickup tick failed: {arg}"); } } } [HarmonyPatch(typeof(Game), "Logout")] internal static class GameLogoutPatch { private static void Prefix() { PickupGuard.ForceRestore(); } } [HarmonyPatch(typeof(Player), "OnDestroy")] internal static class PlayerDestroyPatch { private static void Prefix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer) { PickupGuard.ForceRestore(); } } } internal static class PlayerFields { private static readonly FieldRef<bool> EnableAutoPickup = AccessTools.StaticFieldRefAccess<bool>(AccessTools.DeclaredField(typeof(Player), "m_enableAutoPickup")); private static readonly FieldRef<Player, float> AutoPickupRange = AccessTools.FieldRefAccess<Player, float>(AccessTools.DeclaredField(typeof(Player), "m_autoPickupRange")); internal static bool GetEnabled() { return EnableAutoPickup.Invoke(); } internal static void SetEnabled(bool value, bool announce) { if (GetEnabled() != value) { EnableAutoPickup.Invoke() = value; if (announce) { Announce(); } } } internal static void Announce() { Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer)) { string text = (GetEnabled() ? "$hud_on" : "$hud_off"); ((Character)localPlayer).Message((MessageType)1, "$hud_autopickup:" + text, 0, (Sprite)null, false); } } internal static float GetRange(Player player) { if (!((Object)(object)player == (Object)null)) { return AutoPickupRange.Invoke(player); } return 0f; } } internal static class PickupGuard { private static bool _inZone; private static bool _weSuppressed; private static bool _savedEnabled; private static string _lastReason = "none"; private static readonly List<Character> _tameScratch = new List<Character>(32); internal static void Tick(Player player) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } if (!ModConfig.Enabled.Value) { ForceRestore(); return; } float range = RangeSources.CurrentExclusionRange(player); if (IsInExclusionZone(((Component)player).transform.position, range, out string reason)) { OnInsideZone(reason, range); } else { OnOutsideZone(); } } internal static void ForceRestore() { _inZone = false; RestoreIfNeeded(announce: false); } private static void OnInsideZone(string reason, float range) { if (!_inZone) { _inZone = true; _lastReason = reason; if (PlayerFields.GetEnabled()) { _savedEnabled = true; _weSuppressed = true; PlayerFields.SetEnabled(value: false, announce: true); if (ModConfig.DebugLogs.Value) { Plugin.Log.LogInfo((object)$"Auto-pickup off near {reason} (range {range:0.##})."); } } else if (ModConfig.DebugLogs.Value) { Plugin.Log.LogInfo((object)("Entered " + reason + " zone with auto-pickup already off.")); } return; } if (_weSuppressed && PlayerFields.GetEnabled()) { _weSuppressed = false; _savedEnabled = true; if (ModConfig.DebugLogs.Value) { Plugin.Log.LogInfo((object)"Auto-pickup hotkey turned it back on; leaving it on until you leave this zone."); } } if (ModConfig.DebugLogs.Value && reason != _lastReason) { Plugin.Log.LogInfo((object)("Zone is now " + reason + ".")); } _lastReason = reason; } private static void OnOutsideZone() { if (_inZone || _weSuppressed) { _inZone = false; RestoreIfNeeded(announce: true); } } private static void RestoreIfNeeded(bool announce) { if (_weSuppressed) { PlayerFields.SetEnabled(_savedEnabled, announce); _weSuppressed = false; if (ModConfig.DebugLogs.Value) { Plugin.Log.LogInfo((object)("Auto-pickup restored to " + (_savedEnabled ? "on" : "off") + ".")); } _lastReason = "none"; } } private static bool IsInExclusionZone(Vector3 origin, float range, out string reason) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) reason = "none"; if (range <= 0f) { return false; } if (ModConfig.FiresEnabled.Value && AnyFireInRange(origin, range)) { reason = "campfire/hearth"; return true; } if (ModConfig.TamesEnabled.Value && AnyTameInRange(origin, range)) { reason = "tamed animal"; return true; } if (ModConfig.DrawersEnabled.Value && DrawerApi.AnyInRange(origin, range)) { reason = "item drawer"; return true; } return false; } private static bool AnyFireInRange(Vector3 origin, float range) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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) float num = range * range; foreach (Fireplace item in FireplaceRegistry.All) { if (Object.op_Implicit((Object)(object)item) && Object.op_Implicit((Object)(object)((Component)item).transform)) { Vector3 val = ((Component)item).transform.position - origin; if (!(((Vector3)(ref val)).sqrMagnitude > num) && (!ModConfig.OnlyIfBurning.Value || item.IsBurning()) && ModConfig.IsWatchedFirePrefab(PrefabName(((Component)item).gameObject))) { return true; } } } return false; } private static bool AnyTameInRange(Vector3 origin, float range) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) _tameScratch.Clear(); Character.GetCharactersInRange(origin, range, _tameScratch); foreach (Character item in _tameScratch) { if (Object.op_Implicit((Object)(object)item) && !item.IsPlayer() && item.IsTamed()) { return true; } } return false; } internal static string PrefabName(GameObject go) { if (!Object.op_Implicit((Object)(object)go)) { return string.Empty; } string name = ((Object)go).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num < 0) { return name; } return name.Substring(0, num).Trim(); } } [BepInPlugin("Ageous.NoAutoPickup", "NoAutoPickup", "0.1.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string ModGUID = "Ageous.NoAutoPickup"; public const string ModName = "NoAutoPickup"; public const string ModVersion = "0.1.2"; internal static Plugin Instance; internal static ManualLogSource Log; internal static Harmony Harmony; private void Awake() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); DrawerApi.Init(); Harmony = new Harmony("Ageous.NoAutoPickup"); Harmony.PatchAll(); Log.LogInfo((object)"NoAutoPickup 0.1.2 loaded (client auto-pickup guard)."); } private void OnDestroy() { PickupGuard.ForceRestore(); Harmony harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal static class RangeSources { private static readonly Regex DrawerRange = new Regex("^\\s*DrawerPickupRange\\s*=\\s*([0-9]+(?:\\.[0-9]+)?)\\s*$", RegexOptions.Multiline | RegexOptions.CultureInvariant); private static readonly Regex BiggerRadius = new Regex("^\\s*Radius\\s*=\\s*([0-9]+(?:\\.[0-9]+)?)\\s*$", RegexOptions.Multiline | RegexOptions.CultureInvariant); internal static float CurrentExclusionRange(Player player) { float val = Math.Max(0f, ModConfig.VanillaFloor.Value); float range = PlayerFields.GetRange(player); if (range > 0f) { val = Math.Max(val, range); } val = Math.Max(val, ReadConfigFloat("net.mtnewton.biggerpickupradius.cfg", BiggerRadius)); val = Math.Max(val, ReadConfigFloat("kg.ItemDrawers.cfg", DrawerRange)); float num = Math.Max(0f, ModConfig.RangePadding.Value); return val + num; } private static float ReadConfigFloat(string fileName, Regex pattern) { try { string path = Path.Combine(Paths.ConfigPath, fileName); if (!File.Exists(path)) { return 0f; } Match match = pattern.Match(File.ReadAllText(path)); if (!match.Success) { return 0f; } if (float.TryParse(match.Groups[1].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && result > 0f) { return result; } } catch (Exception ex) { if (ModConfig.DebugLogs.Value) { Plugin.Log.LogWarning((object)("Failed reading " + fileName + ": " + ex.Message)); } } return 0f; } } }