OnInventoryItemsCount
OnInventoryItemsCount is called from PlayerInventory.GetAmount before the game sums item stacks, letting a plugin supply the item count for an inventory instead of the vanilla total.
object OnInventoryItemsCount(PlayerInventory playerInventory, int itemid, bool includeBackpack, bool redirectAllowed)Parameters
| Parameter | Type | Description |
|---|---|---|
playerInventory | PlayerInventory | The PlayerInventory whose items are being counted. Use its containers (containerMain, containerBelt, containerWear, and the backpack container if present) to run your own count. |
itemid | int | The item definition ID being counted. The original method short-circuits to 0 when this is 0, so the hook is not reached in that case. |
includeBackpack | bool | Whether the caller wants backpack contents included in the count. Mirror this when you compute your own total so results stay consistent with what the caller expects. |
redirectAllowed | bool | Whether the caller permits a redirect to another player's inventory. Return null if your logic only applies when the count should stay local to this inventory. |
Return value
Return an int to skip the vanilla counting loop; that value becomes the result of PlayerInventory.GetAmount. Return null (or any non-int value) to let the original method compute the count as usual.
How it works
This hook fires inside PlayerInventory.GetAmount(int itemid, bool includeBackpack, bool redirectAllowed), right after the early return for itemid == 0 and immediately before the game starts looping over containers to add up stack amounts. Every call to GetAmount on a player inventory goes through it, so it runs whenever the game asks "how many of this item does this player have?" — crafting checks, ammo checks, deploy limits, quest-style counters and your own plugin code all route through here.
The first parameter is the inventory itself, so you can inspect containerMain, containerBelt, containerWear and the backpack when includeBackpack is true. The itemid tells you which item is wanted and matches ItemDefinition.itemid. redirectAllowed signals that the caller tolerates counting against a different inventory; if your logic does not care about that, ignore it.
Because the hook returns object, returning an int short-circuits the vanilla count and that value is handed back to the caller. Return null to let the game count normally. Keep the handler fast — it can be called many times per frame during inventory-heavy actions.
Example plugin: Reward virtual backpack items in inventory counts
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Backpack Item Counter", "RustPluginGenerator", "1.0.0")]
[Description("Adds permission-based virtual item counts to player inventory totals.")]
public class BackpackItemCounter : RustPlugin
{
private PluginConfig config;
private readonly Dictionary<int, List<BonusEntry>> bonusByItem = new Dictionary<int, List<BonusEntry>>();
private class BonusEntry
{
[JsonProperty("Item shortname")]
public string Shortname = "scrap";
[JsonProperty("Bonus amount")]
public int Amount = 50;
[JsonProperty("Required permission")]
public string Permission = "backpackitemcounter.bonus";
}
private class PluginConfig
{
[JsonProperty("Bonus entries")]
public List<BonusEntry> Entries = new List<BonusEntry>
{
new BonusEntry { Shortname = "scrap", Amount = 50, Permission = "backpackitemcounter.bonus" }
};
}
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()
{
foreach (var entry in config.Entries)
{
if (string.IsNullOrEmpty(entry.Permission)) continue;
permission.RegisterPermission(entry.Permission, this);
}
}
private void OnServerInitialized()
{
bonusByItem.Clear();
foreach (var entry in config.Entries)
{
if (string.IsNullOrEmpty(entry.Shortname)) continue;
var def = ItemManager.FindItemDefinition(entry.Shortname);
if (def == null) continue;
if (!bonusByItem.TryGetValue(def.itemid, out var list))
{
list = new List<BonusEntry>();
bonusByItem[def.itemid] = list;
}
list.Add(entry);
}
}
private object OnInventoryItemsCount(PlayerInventory playerInventory, int itemid, bool includeBackpack, bool redirectAllowed)
{
if (playerInventory == null || itemid == 0) return null;
if (!bonusByItem.TryGetValue(itemid, out var entries)) return null;
var player = playerInventory.baseEntity as BasePlayer;
if (player == null || !player.IsConnected) return null;
int bonus = 0;
foreach (var entry in entries)
{
if (permission.UserHasPermission(player.UserIDString, entry.Permission))
{
bonus += entry.Amount;
}
}
if (bonus <= 0) return null;
int baseCount = CountItems(playerInventory, itemid, includeBackpack);
return baseCount + bonus;
}
private int CountItems(PlayerInventory inv, int itemid, bool includeBackpack)
{
int total = 0;
total += CountInContainer(inv.containerMain, itemid);
total += CountInContainer(inv.containerBelt, itemid);
total += CountInContainer(inv.containerWear, itemid);
return total;
}
private int CountInContainer(ItemContainer container, int itemid)
{
if (container == null) return 0;
int total = 0;
foreach (var item in container.itemList)
{
if (item.info.itemid == itemid) total += item.amount;
}
return total;
}
}
}The plugin lets admins add a virtual quantity of any item to a player's effective inventory total without physically placing items in a container. Configuration stores a list of entries, each with a permission, item shortname, and bonus amount. When OnInventoryItemsCount fires, the plugin checks that the player is connected and collects all entries matching the requested itemid. It sums the bonus amounts for every entry whose permission the player has. If the total bonus is positive, it returns its own count of the item in the player's main, belt, and wear containers plus that bonus. It returns null when there is no matching item, no permission, or the player is disconnected, leaving the default count unchanged.
Common use cases
Permission-based bonus counts
Give donors or VIPs a virtual stock of an item for crafting checks, without actually spawning items into their containers.
Quest and objective tracking
Accumulate counts from custom sources (e.g. scored rewards) so other systems that call GetAmount see the player's progress.
Blocking specific items
Return 0 for blocked items so crafting or usage checks that rely on GetAmount fail even when the item is present.
Pitfalls
Returned int is authoritative
Once you return a number, the game trusts it and does not add its own count. Always compute the base count yourself when returning a value, or you will under-report.
Called very frequently
Every GetAmount call routes through this hook, including internal crafting and ammo checks. Cache permission and configuration lookups rather than re-reading data each call.
Null playerInventory
Guard against a null
playerInventoryand a missing owner; PlayerInventory instances can exist for entities without a connected player.
Build a plugin with OnInventoryItemsCount
Describe what should happen and get a compiled plugin that uses this hook.
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 OnInventoryItemsCount
Generate