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 KuickStash v1.0.0
KuickStash.dll
Decompiled 20 hours 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 HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [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("KuickStash")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("KuickStash")] [assembly: AssemblyTitle("KuickStash")] [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 KuickStash { [BepInPlugin("de.example.valheim.kuickstash", "KuickStash", "1.0.0")] public class KuickStashPlugin : BaseUnityPlugin { private ConfigEntry<KeyCode> _sortKey; private ConfigEntry<float> _range; private ConfigEntry<bool> _onlyMatching; private ConfigEntry<bool> _skipHotbar; private ConfigEntry<bool> _storeRawFood; private static readonly FieldInfo NviewField = AccessTools.Field(typeof(Container), "m_nview"); private static readonly MethodInfo CheckAccessMethod = AccessTools.Method(typeof(Container), "CheckAccess", new Type[1] { typeof(long) }, (Type[])null); private static readonly MethodInfo ChangedMethod = (from m in typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where m.Name == "Changed" orderby m.GetParameters().Length select m).FirstOrDefault(); private static readonly HashSet<ItemType> KeptTypes = new HashSet<ItemType> { (ItemType)2, (ItemType)9, (ItemType)23, (ItemType)19, (ItemType)15, (ItemType)3, (ItemType)14, (ItemType)22, (ItemType)20, (ItemType)4, (ItemType)5, (ItemType)6, (ItemType)7, (ItemType)11, (ItemType)12, (ItemType)17, (ItemType)18, (ItemType)24 }; private static HashSet<string> _cookedFoods; private static bool _errorLogged; private void Awake() { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Inventory.Changed: " + (ChangedMethod?.ToString() ?? "NOT FOUND"))); _sortKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "SortKey", (KeyCode)107, "Taste zum Einsortieren"); _range = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Range", 20f, "Radius in Metern, in dem Kisten gesucht werden"); _onlyMatching = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "OnlyMatchingChests", true, "true = nur in Kisten, die das Item schon enthalten; false = in jede Kiste mit freiem Platz"); _storeRawFood = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "StoreRawFood", true, "true = uncooked food (berries, mushrooms, honey, ...) is stashed, only cooked food and potions are kept; false = all food is kept"); _skipHotbar = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "SkipHotbar", true, "true = Items in der obersten Inventarreihe (Hotbar) nie verschieben"); } private void Update() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && Input.GetKeyDown(_sortKey.Value) && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !Menu.IsVisible() && !TextInput.IsVisible() && !((Character)localPlayer).InCutscene()) { int num = SortInventory(localPlayer); ((Character)localPlayer).Message((MessageType)1, (num > 0) ? $"{num} Gegenstände einsortiert" : "Nichts einzusortieren", 0, (Sprite)null, false); } } private int SortInventory(Player player) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) Inventory inventory = ((Humanoid)player).GetInventory(); List<Container> list = FindContainers(((Component)player).transform.position); int num = 0; foreach (ItemData item in inventory.GetAllItems().ToList()) { if (item.m_equipped || item.m_shared.m_questItem || IsKept(item) || (_skipHotbar.Value && item.m_gridPos.y == 0)) { continue; } int num2 = item.m_stack; foreach (Container item2 in list) { if (num2 <= 0) { break; } try { int num3 = MoveToContainer(inventory, item, item2, num2); num += num3; num2 -= num3; } catch (Exception ex) { if (!_errorLogged) { _errorLogged = true; ((BaseUnityPlugin)this).Logger.LogError((object)("Error while moving items: " + ex)); } } } } return num; } private bool IsKept(ItemData item) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_002c: Unknown result type (might be due to invalid IL or missing references) SharedData shared = item.m_shared; if ((int)shared.m_itemType != 2 || !_storeRawFood.Value) { return KeptTypes.Contains(shared.m_itemType); } bool flag = shared.m_food > 0f || shared.m_foodStamina > 0f || shared.m_foodEitr > 0f; HashSet<string> cookedFoods = GetCookedFoods(); return !flag || cookedFoods == null || cookedFoods.Contains(shared.m_name); } private HashSet<string> GetCookedFoods() { if (_cookedFoods != null || (Object)(object)ZNetScene.instance == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return _cookedFoods; } try { IEnumerable<string> first = from conv in (from p in ZNetScene.instance.m_prefabs where (Object)(object)p != (Object)null select p.GetComponent<CookingStation>() into c where (Object)(object)c != (Object)null select c).SelectMany((CookingStation c) => c.m_conversion) where (Object)(object)conv.m_to != (Object)null select conv.m_to.m_itemData.m_shared.m_name; IEnumerable<string> second = from r in ObjectDB.instance.m_recipes where (Object)(object)r != (Object)null && (Object)(object)r.m_item != (Object)null && (Object)(object)r.m_craftingStation != (Object)null && r.m_craftingStation.m_name == "$piece_cauldron" select r.m_item.m_itemData.m_shared.m_name; _cookedFoods = new HashSet<string>(first.Concat(second)); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not build the list of cooked foods: " + ex)); } return _cookedFoods; } private int MoveToContainer(Inventory playerInv, ItemData item, Container container, int remaining) { Inventory inventory = container.GetInventory(); object? value = NviewField.GetValue(container); ZNetView nview = (ZNetView)((value is ZNetView) ? value : null); if (inventory == null || (Object)(object)nview == (Object)null || !nview.IsValid()) { return 0; } if (_onlyMatching.Value && !inventory.HaveItem(item.m_shared.m_name, true)) { return 0; } int moved = 0; bool claimed = false; foreach (ItemData allItem in inventory.GetAllItems()) { if (remaining <= 0) { break; } int num = allItem.m_shared.m_maxStackSize - allItem.m_stack; if (!(allItem.m_shared.m_name != item.m_shared.m_name) && allItem.m_quality == item.m_quality && num > 0) { int num2 = Mathf.Min(remaining, num); Claim(); allItem.m_stack += num2; TakeFromPlayer(num2); } } if (remaining > 0) { ItemData val = item.Clone(); val.m_stack = remaining; if (inventory.CanAddItem(val, -1)) { Claim(); if (inventory.AddItem(val)) { TakeFromPlayer(remaining); } } } if (claimed) { NotifyChanged(inventory); } return moved; void Claim() { if (!claimed) { nview.ClaimOwnership(); claimed = true; } } void TakeFromPlayer(int n) { if (n >= item.m_stack) { playerInv.RemoveItem(item); } else { playerInv.RemoveItem(item, n); } remaining -= n; moved += n; } } private static void NotifyChanged(Inventory inv) { object[] parameters = (from p in ChangedMethod?.GetParameters() select p.HasDefaultValue ? p.DefaultValue : (p.ParameterType.IsValueType ? Activator.CreateInstance(p.ParameterType) : null)).ToArray(); ChangedMethod?.Invoke(inv, parameters); } private static bool HasAccess(Container c, long playerId) { return (bool)(CheckAccessMethod?.Invoke(c, new object[1] { playerId }) ?? ((object)false)); } private List<Container> FindContainers(Vector3 center) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) long playerId = Player.m_localPlayer.GetPlayerID(); return (from c in (from col in Physics.OverlapSphere(center, _range.Value) select ((Component)col).GetComponentInParent<Container>() into c where (Object)(object)c != (Object)null select c).Distinct() where !c.IsInUse() && HasAccess(c, playerId) && PrivateArea.CheckAccess(((Component)c).transform.position, 0f, false, false) select c).OrderBy(delegate(Container c) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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) Vector3 val = ((Component)c).transform.position - center; return ((Vector3)(ref val)).sqrMagnitude; }).ToList(); } } }