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 Restock v0.1.0
plugins/Restock.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Restock")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Restock")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.1.0")] [assembly: IgnoresAccessChecksTo("assembly_utils")] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] namespace Restock { internal enum SelectionMode { Click, Hover, Both } [BepInPlugin("orax.Restock", "Restock", "0.1.0")] internal class Restock : BaseUnityPlugin { public const string PluginGUID = "orax.Restock"; public const string PluginName = "Restock"; public const string PluginVersion = "0.1.0"; private const string MessageHint = " Leave it empty to disable the message."; internal static ManualLogSource Log { get; private set; } internal static Restock Instance { get; private set; } internal ConfigEntry<KeyboardShortcut> Hotkey { get; private set; } internal ConfigEntry<string> MessageNothingSelected { get; private set; } internal ConfigEntry<string> MessageNoMatchingItems { get; private set; } internal ConfigEntry<string> MessageNoSpace { get; private set; } internal ConfigEntry<string> MessageTooHeavy { get; private set; } internal ConfigEntry<bool> DeselectAfterRestock { get; private set; } internal ConfigEntry<SelectionMode> ItemSelectionMode { get; private set; } private void Awake() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Instance = this; Hotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Input", "Hotkey", new KeyboardShortcut((KeyCode)114, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Key combination pressed while a container is open to pull the items matching the selected one into the player inventory. The main key is written first and the modifiers after it: R + LeftShift is the combination Shift + R. A single key (B) works too, and None disables the hotkey."); DeselectAfterRestock = ((BaseUnityPlugin)this).Config.Bind<bool>("Behaviour", "DeselectAfterRestock", true, "Put the selection down when the restock key is pressed, whatever the outcome: the item stays where it was and the next press needs a new selection. Set it to false to keep the selection and press the key again right away."); ItemSelectionMode = ((BaseUnityPlugin)this).Config.Bind<SelectionMode>("Behaviour", "SelectionMode", SelectionMode.Both, "How the item to restock is picked. Click: the item selected with a plain left click. Hover: the item under the mouse cursor when the key is pressed, no click needed. Both: the hovered item when there is one, otherwise the clicked one."); MessageNothingSelected = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "NothingSelected", "Restock: select an item first", "Shown when the hotkey is pressed without a hovered or selected item. Leave it empty to disable the message."); MessageNoMatchingItems = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "NoMatchingItems", "Restock: no matching items in the container", "Shown when the container holds no item identical to the selected one. Leave it empty to disable the message."); MessageNoSpace = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "NoSpace", "Restock: not enough room in your inventory", "Shown when the transfer stops because your inventory has no room left. Leave it empty to disable the message."); MessageTooHeavy = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "TooHeavy", "Restock: that would make you overburdened", "Shown when the transfer stops because it would exceed your maximum carry weight. Leave it empty to disable the message."); ManualLogSource log = Log; KeyboardShortcut value = Hotkey.Value; log.LogInfo((object)("Restock 0.1.0 loaded (hotkey: " + ((KeyboardShortcut)(ref value)).Serialize() + ")")); } internal bool IsHotkeyPressed() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = Hotkey.Value; return ((KeyboardShortcut)(ref value)).IsDown(); } private void Update() { Restocker.Update(); } } internal static class Restocker { private enum Result { Moved, NothingSelected, NoMatchingItems, NoSpace, TooHeavy, Cancelled } private static InventoryGui _boundGui; private static Container _boundContainer; private static ItemData _selected; internal static void Update() { InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { ResetState(); return; } if (_boundGui != instance) { Rebind(instance); } Container currentContainer = instance.m_currentContainer; if (_boundContainer != currentContainer) { _boundContainer = currentContainer; _selected = null; } if ((Object)(object)currentContainer == (Object)null || InventoryGui.WaitForStack() || ((Object)(object)instance.m_splitDialog != (Object)null && instance.m_splitDialog.IsActive) || Console.IsVisible() || TextInput.IsVisible() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) || !Restock.Instance.IsHotkeyPressed()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsTeleporting()) { return; } try { Result result = RestockFromContainer(instance, localPlayer, currentContainer); if (result != Result.Moved && result != Result.Cancelled) { string text = Message(result); if (!string.IsNullOrEmpty(text)) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } if (result != Result.Cancelled && result != Result.NothingSelected && (Object)(object)Restock.Instance != (Object)null && Restock.Instance.DeselectAfterRestock.Value) { DropSelection(instance); } } catch (Exception arg) { Restock.Log.LogError((object)$"Restock failed: {arg}"); } } private static Result RestockFromContainer(InventoryGui gui, Player player, Container container) { //IL_0231: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) _selected = ResolveSelection(gui, player, container); if (_selected == null) { return Result.NothingSelected; } if (!container.IsOwner()) { Restock.Log.LogWarning((object)"Restock: container is not owned by this player, cancelled"); return Result.Cancelled; } Inventory inventory = ((Humanoid)player).GetInventory(); Inventory inventory2 = container.GetInventory(); if (inventory == null || inventory2 == null) { return Result.Cancelled; } List<ItemData> list = inventory2.GetAllItems().FindAll((ItemData item) => item != null && item.m_stack > 0 && item.IsSameType(_selected)); if (list.Count == 0) { return Result.NoMatchingItems; } int num = 0; int num2 = 0; bool flag = false; foreach (ItemData item in new List<ItemData>(inventory.GetAllItems())) { if (flag || num2 >= list.Count) { break; } if (!item.IsSameType(_selected)) { continue; } while (num2 < list.Count && item.m_stack < item.m_shared.m_maxStackSize) { ItemData val = list[num2]; int num3 = AllowedUnits(player, inventory, val); if (num3 <= 0) { flag = true; break; } int amount = Math.Min(Math.Min(item.m_shared.m_maxStackSize - item.m_stack, val.m_stack), num3); int num4 = Transfer(inventory, inventory2, val, amount, item.m_gridPos); if (num4 <= 0) { break; } num += num4; if (val.m_stack <= 0) { num2++; } } } while (num2 < list.Count && !flag) { Vector2i val2 = FindFreeSlot(inventory, _selected); if (val2.x < 0) { break; } ItemData val3 = list[num2]; int num5 = AllowedUnits(player, inventory, val3); if (num5 <= 0) { flag = true; break; } int amount2 = Math.Min(Math.Min(val3.m_shared.m_maxStackSize, val3.m_stack), num5); int num6 = Transfer(inventory, inventory2, val3, amount2, val2); if (num6 <= 0) { break; } num += num6; if (val3.m_stack <= 0) { num2++; } } if (num <= 0) { if (!flag) { return Result.NoSpace; } return Result.TooHeavy; } ReleaseStaleDrag(gui); gui.m_moveItemEffects.Create(((Component)gui).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); Restock.Log.LogInfo((object)($"Restocked {num} x {_selected.m_shared.m_name} " + "from '" + inventory2.GetName() + "'")); return Result.Moved; } private static ItemData ResolveSelection(InventoryGui gui, Player player, Container container) { Restock instance = Restock.Instance; SelectionMode selectionMode = ((!((Object)(object)instance == (Object)null)) ? instance.ItemSelectionMode.Value : SelectionMode.Click); if (selectionMode == SelectionMode.Click) { return _selected; } ItemData val = FindHoveredItem(gui.ContainerGrid, container.GetInventory()); if (val == null) { val = FindHoveredItem(gui.m_playerGrid, ((Humanoid)player).GetInventory()); } if (val != null) { return val; } if (selectionMode != SelectionMode.Hover) { return _selected; } return null; } private static ItemData FindHoveredItem(InventoryGrid grid, Inventory inventory) { //IL_0034: 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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)grid == (Object)null || inventory == null) { return null; } foreach (InventoryElement element in grid.m_elements) { if (!((Object)(object)element == (Object)null)) { RectTransform elementRectTransform = element.GetElementRectTransform(); Vector2 val = Vector2.op_Implicit(((Transform)elementRectTransform).InverseTransformPoint(ZInput.pointerPosition)); Rect rect = elementRectTransform.rect; if (((Rect)(ref rect)).Contains(val)) { Vector2i position = element.Position; return inventory.GetItemAt(position.x, position.y); } } } return null; } private static int AllowedUnits(Player player, Inventory inventory, ItemData item) { float weight = item.GetWeight(1); if (weight <= 0f) { return int.MaxValue; } float maxCarryWeight = player.GetMaxCarryWeight(); float num = maxCarryWeight - inventory.GetTotalWeight(); if (num <= 0f) { return 0; } double num2 = num / weight; if (num2 >= 2147483647.0) { return int.MaxValue; } int num3 = (int)num2; while (num3 > 0 && inventory.GetTotalWeight() + weight * (float)num3 > maxCarryWeight) { num3--; } return num3; } private static int Transfer(Inventory to, Inventory from, ItemData source, int amount, Vector2i pos) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (amount <= 0) { return 0; } int stack = source.m_stack; to.MoveItemToThis(from, source, amount, pos.x, pos.y); return Math.Max(0, stack - source.m_stack); } private static Vector2i FindFreeSlot(Inventory inventory, ItemData selected) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Invalid comparison between Unknown and I4 //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) bool flag = selected.IsWeapon() || (int)selected.m_shared.m_itemType == 19 || (int)selected.m_shared.m_itemType == 5 || (int)selected.m_shared.m_itemType == 18 || (int)selected.m_shared.m_itemType == 16 || (int)selected.m_shared.m_itemType == 24; int num = inventory.GetHeight() - 1; for (int i = 0; i <= num; i++) { int num2 = (flag ? i : (num - i)); for (int j = 0; j < inventory.GetWidth(); j++) { if (inventory.GetItemAt(j, num2) == null) { return new Vector2i(j, num2); } } } return new Vector2i(-1, -1); } private static void DropSelection(InventoryGui gui) { _selected = null; ClearDrag(gui); } private static void ClearDrag(InventoryGui gui) { if ((Object)(object)gui.m_dragGo != (Object)null) { Object.Destroy((Object)(object)gui.m_dragGo); gui.m_dragGo = null; } gui.m_dragItem = null; gui.m_dragInventory = null; gui.m_dragAmount = 0; } private static void ReleaseStaleDrag(InventoryGui gui) { ItemData dragItem = gui.m_dragItem; if (dragItem != null && gui.m_dragInventory != null && !gui.m_dragInventory.ContainsItem(dragItem)) { ClearDrag(gui); } } private static void Rebind(InventoryGui gui) { if ((Object)(object)_boundGui != (Object)null && _boundGui != gui) { Unhook(_boundGui); } _boundGui = gui; _selected = null; Hook(gui); } private static void Hook(InventoryGui gui) { if ((Object)(object)gui.m_playerGrid != (Object)null) { InventoryGrid playerGrid = gui.m_playerGrid; playerGrid.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Remove(playerGrid.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); InventoryGrid playerGrid2 = gui.m_playerGrid; playerGrid2.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Combine(playerGrid2.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); } if ((Object)(object)gui.ContainerGrid != (Object)null) { InventoryGrid containerGrid = gui.ContainerGrid; containerGrid.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Remove(containerGrid.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); InventoryGrid containerGrid2 = gui.ContainerGrid; containerGrid2.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Combine(containerGrid2.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); } } private static void Unhook(InventoryGui gui) { if ((Object)(object)gui.m_playerGrid != (Object)null) { InventoryGrid playerGrid = gui.m_playerGrid; playerGrid.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Remove(playerGrid.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); } if ((Object)(object)gui.ContainerGrid != (Object)null) { InventoryGrid containerGrid = gui.ContainerGrid; containerGrid.m_onSelected = (Action<InventoryGrid, ItemData, Vector2i, Modifier>)Delegate.Remove(containerGrid.m_onSelected, new Action<InventoryGrid, ItemData, Vector2i, Modifier>(OnItemSelected)); } } private static void ResetState() { if ((Object)(object)_boundGui != (Object)null) { Unhook(_boundGui); } _boundGui = null; _boundContainer = null; _selected = null; } private static void OnItemSelected(InventoryGrid grid, ItemData item, Vector2i pos, Modifier modifier) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)modifier == 0) { _selected = item; } } private static string Message(Result result) { Restock instance = Restock.Instance; if ((Object)(object)instance == (Object)null) { return string.Empty; } return result switch { Result.NothingSelected => instance.MessageNothingSelected.Value, Result.NoMatchingItems => instance.MessageNoMatchingItems.Value, Result.NoSpace => instance.MessageNoSpace.Value, Result.TooHeavy => instance.MessageTooHeavy.Value, _ => string.Empty, }; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }