Skip to content
RustPluginGenerator

OnInventoryItemsTake

OnInventoryItemsTake is called at the start of PlayerInventory.Take, before the game removes items from a player's inventory containers.

Signature
object OnInventoryItemsTake(PlayerInventory playerInventory, List<Item> collect, int itemid, int amount)

Parameters

Hook parameters
ParameterTypeDescription
playerInventoryPlayerInventoryThe PlayerInventory instance the Take call is running on. Use its playerOwner to identify the player whose container is being drained.
collectList<Item>The list the removed items are written into. If you return an int, the game skips its own removal, so this list stays empty unless you fill it yourself.
itemidintThe itemid (definition id) being taken, matching ItemDefinition.itemid. Not a shortname string.
amountintHow many units of the item the caller wants to remove. This is the requested amount, not what was actually found.

Return value

Returning null lets the normal Take logic run and the real number of removed items is returned. Returning an int skips the original removal loop entirely, the result becomes that integer, and no items are actually withdrawn unless you remove them yourself.

How it works

The hook fires inside PlayerInventory.Take(List<Item> collect, int itemid, int amount), a method the game uses to pull a number of items out of a player's inventory and record what was removed. That happens during crafting cost checks, ammo consumption, recycling, exchanging, and many internal game operations that need to subtract items. Because the hook runs before the removal loop, playerInventory is the inventory being drained, collect is the list the removed Item objects will be added to, and itemid is the definition id being taken.

The parameters are useful for audit and rule enforcement: you can read playerInventory.playerOwner to know who is affected, compare itemid against ItemManager.FindItemDefinition lookups, and inspect amount to decide whether to allow the call. Declaring playerInventory as PlayerInventory is already the exact type, so there is no narrower overload to exploit here; filtering is done inside your method body instead.

Return an integer to take over the method: that number becomes the count the caller believes was removed. Since this fires frequently, do not print to console inside it and keep the body cheap.

Example plugin: Block moving blacklisted items out of inventories

InventoryTakeGuard.cs
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;

namespace Oxide.Plugins
{
    [Info("Inventory Take Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks configured items from being silently removed via PlayerInventory.Take")]
    public class InventoryTakeGuard : RustPlugin
    {
        private const string PermBypass = "inventorytakeguard.bypass";

        private class PluginConfig
        {
            [JsonProperty("Blocked item shortnames")]
            public List<string> BlockedShortnames = new List<string> { "scrap", "rifle.ak", "explosive.timed" };
        }

        private PluginConfig config;
        private HashSet<int> blockedItemIds = new HashSet<int>();

        protected override void LoadDefaultConfig() => config = new PluginConfig();

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<PluginConfig>();
                if (config == null) throw new Exception();
            }
            catch
            {
                PrintWarning("Configuration file is invalid, using defaults");
                LoadDefaultConfig();
            }
            SaveConfig();
        }

        protected override void SaveConfig() => Config.WriteObject(config);

        private void Init()
        {
            permission.RegisterPermission(PermBypass, this);
            blockedItemIds.Clear();
            if (config?.BlockedShortnames == null) return;
            foreach (var shortname in config.BlockedShortnames)
            {
                var def = ItemManager.FindItemDefinition(shortname);
                if (def == null) continue;
                blockedItemIds.Add(def.itemid);
            }
        }

        private object OnInventoryItemsTake(PlayerInventory playerInventory, List<Item> collect, int itemid, int amount)
        {
            if (playerInventory == null || !blockedItemIds.Contains(itemid)) return null;
            var owner = playerInventory.containerMain?.playerOwner;
            if (owner == null || owner.IsNpc) return null;
            if (owner.IsAdmin || permission.UserHasPermission(owner.UserIDString, PermBypass)) return null;
            // Return zero so the game reports nothing removed and does not run its removal loop.
            return 0;
        }
    }
}

The plugin keeps a list of item shortnames in its config that should never be cleanly removed from a player's inventory. LoadDefaultConfig seeds a sane default, and OnInventoryItemsTake resolves itemid to an ItemDefinition, then checks it against the configured set. If the item is blacklisted and belongs to a real player, the hook returns 0 so the game skips its removal loop and the caller sees zero items taken. Admins holding the inventorytakeguard.bypass permission are left alone. Because this hook runs often, the method only does a dictionary lookup and an optional permission check.

Common use cases

  • Track crafting material consumption

    Compare itemid against known resource ids and keep a running counter per player so you can report how much scrap or ore they spend.

  • Stop item smuggling through server actions

    Return 0 for blacklisted items to prevent internal game operations from silently pulling them out of inventories.

  • Bypass restrictions for staff

    Check permission on playerInventory.playerOwner and return null early so admins always interact with the normal Take behavior.

Pitfalls

  • Returning a count does not remove items

    A non-null int replaces the method result and skips the original loop, so nothing is actually taken. If you want to remove items yourself, modify collect and the containers explicitly.

  • Fires for NPC and non-player inventories

    playerOwner can be null, for example on some player-less containers. Always null-check before reading UserIDString or calling permission checks.

  • Called very frequently

    Take runs during crafting, ammo use and many internal loops. Avoid logging, string formatting or allocation-heavy work inside this hook.

Build a plugin with OnInventoryItemsTake

Describe what should happen and get a compiled plugin that uses this hook.

Prompt: Track crafting material consumption using the OnInventoryItemsTake hook, with a config file and a permission
Generate this plugin

Edit the prompt on the next screen. 2 free plugins a month, no card.

Last updated Oct 26, 2026. Found a mistake? Email support@rustplugingenerator.com.

Build a plugin with OnInventoryItemsTake

Generate