OnInventoryItemFind
OnInventoryItemFind is called when PlayerInventory.FindItemByItemID looks up an item of a given definition id in a player's inventory; returning an Item overrides the normal search result.
object OnInventoryItemFind(PlayerInventory playerInventory, int id)Parameters
| Parameter | Type | Description |
|---|---|---|
playerInventory | PlayerInventory | The PlayerInventory instance the lookup is running on. Use playerInventory.playerOwner to reach the owning BasePlayer, or check the container fields if you need to inspect carried items. |
id | int | The item definition id (ItemDefinition.itemid) being searched for. Compare it with item.info.itemid values to decide whether to substitute a result. |
Return value
Return an Item to replace the lookup result entirely; the game never inspects the inventory containers and the method returns your item. Return null to leave the original search untouched.
How it works
This hook fires inside PlayerInventory.FindItemByItemID(int id), which the game uses whenever code needs an item of a specific definition from a player's inventory — for example checking whether a player carries an item, resolving a reference for a use action, or validating a requirement before consuming something. Oxide calls the hook before the method walks containerMain and the rest of the inventory. The playerInventory parameter is the inventory being searched and doubles as the way to reach the owner (playerInventory.playerOwner), while id is the ItemDefinition.itemid being requested.
Returning a non-null Item short-circuits the whole method: that item becomes the return value and the vanilla containers are never checked. Returning null (the usual case) lets the original lookup run unchanged. Because the hook cannot distinguish which caller triggered the search, overriding the result affects every game system that calls this method for that inventory until you stop returning the item — it is a global substitution for that inventory, not a one-time injection.
Example plugin: Substitute a virtual item for a search
using System;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Inventory Find Override", "RustPluginGenerator", "1.0.0")]
[Description("Substitutes a configured item when a player's inventory is searched for it by definition id.")]
public class InventoryFindOverride : RustPlugin
{
private const string PermUse = "inventoryfindoverride.use";
private PluginConfig config;
private ulong overrideUserId;
public class PluginConfig
{
[JsonProperty("Item shortname to substitute")]
public string Shortname = "scrap";
}
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(PermUse, this);
}
private void Unload()
{
overrideUserId = 0UL;
}
private void OnServerInitialized()
{
if (ItemManager.FindItemDefinition(config.Shortname) == null)
{
PrintWarning($"Item shortname '{config.Shortname}' was not found; the override will never match.");
}
}
private object OnInventoryItemFind(PlayerInventory playerInventory, int id)
{
if (playerInventory == null || overrideUserId == 0UL) return null;
BasePlayer player = playerInventory.containerMain?.playerOwner;
if (player == null || player.userID.Get() != overrideUserId) return null;
ItemDefinition definition = ItemManager.FindItemDefinition(config.Shortname);
if (definition == null || definition.itemid != id) return null;
foreach (Item item in playerInventory.containerMain.itemList)
{
if (item == null || item.info == null) continue;
if (item.info.itemid == id) return item;
}
return null;
}
[ChatCommand("findoverride")]
private void CmdFindOverride(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage("You do not have permission to use this command.");
return;
}
if (overrideUserId == player.userID.Get())
{
overrideUserId = 0UL;
player.ChatMessage("Inventory find override disabled.");
return;
}
overrideUserId = player.userID.Get();
player.ChatMessage($"Inventory find override enabled for '{config.Shortname}' lookups on your inventory.");
}
}
}The plugin stores the user id of the player for whom the override is active, set by toggling the findoverride chat command (requires inventoryfindoverride.use). While that id is set, OnInventoryItemFind checks whether the requested definition id matches the configured shortname; if it does, it returns the matching item from the player's main container so the vanilla search is skipped. Otherwise it returns null. The command toggles the override on or off for the caller, and Unload clears the stored id. OnServerInitialized warns if the configured shortname does not resolve to an item definition.
Common use cases
Make a virtual currency item visible to vanilla checks
If your plugin represents currency in its own data file, return a real backing item from this hook so game code that asks the inventory for that item id sees it.
Prioritize a specific copy of an item
When a player carries several copies with different skins or conditions, return the one you want game systems to bind to instead of letting the default container order decide.
Hide a stack from vanilla searches
You cannot return 'nothing found' directly, but you can combine this hook with removing or moving the item before the lookup so downstream code does not pick it up.
Pitfalls
You cannot force a not-found result
Returning null means 'use the default search', not 'item absent'. To suppress a lookup you must change the inventory contents instead, because the injection only accepts an Item return value.
The override is global while it lasts
The hook does not know which system called the method, so returning an item affects every FindItemByItemID call on that inventory until you stop. Keep the condition as narrow as possible.
Fires on a hot path
FindItemByItemID is used constantly by gameplay code. Avoid allocations, chat messages or data writes inside the hook and cache anything you need at load time.
Build a plugin with OnInventoryItemFind
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 OnInventoryItemFind
Generate