OnItemPickup
OnItemPickup is called when a player sends the pickup RPC on a WorldItem lying in the world, before the server moves that item into their inventory. Returning a non-null value cancels the pickup.
object OnItemPickup(Item item, BasePlayer player, WorldItem worldItem)Parameters
| Parameter | Type | Description |
|---|---|---|
item | Item | The Item instance sitting inside the world item. Read its info.shortname, amount, skin and condition to identify what is being taken. |
player | BasePlayer | The BasePlayer sending the pickup RPC. Use it for permission checks, inventory access and chat feedback. |
worldItem | WorldItem | The WorldItem entity the player is looting from the ground. Useful for its net.ID.Value, transform.position and OwnerID. |
Return value
Returning null (or any value that is not a valid return type) lets the pickup continue normally. Returning any non-null object cancels the pickup: the item stays in the world and nothing is added to the player's inventory.
How it works
The hook fires inside WorldItem.Pickup(RPCMessage msg), which the client sends when a player looks at a dropped world item and presses the pickup key. It runs after the basic interaction and safe-zone checks but before the pickup sound, the item transfer into the player's inventory and the removal of the world entity.
item is the actual Item object stored on the world entity, so item.info.shortname, item.amount and item.skin describe exactly what would be taken. player is the requester, and worldItem is the entity itself, useful for position-based rules or for logging worldItem.net.ID.Value.
Because the routing parameter types are Item, BasePlayer and WorldItem, declaring a different type for any of them means the hook is skipped for that call. Keep the exact types; use the item.info checks to filter by shortname instead. This hook only covers ground pickups, not looting containers, and it does not fire for server-side GiveItem calls.
Example plugin: Block pickup of restricted items and of other players' drops
using System.Linq;
using UnityEngine;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Pickup Guard", "RustPluginGenerator", "1.0.0")]
[Description("Blocks picking up configured items and other players' world drops")]
public class PickupGuard : RustPlugin
{
private const string PermBypass = "pickupguard.bypass";
private PluginConfig config;
private readonly Dictionary<ulong, float> lastNotice = new Dictionary<ulong, float>();
private class PluginConfig
{
[JsonProperty("Blocked item shortnames")]
public List<string> BlockedShortnames = new List<string> { "supply.signal" };
[JsonProperty("Protect other players' drops")]
public bool ProtectOwnedDrops = true;
[JsonProperty("Seconds between blocked pickup messages")]
public float NoticeCooldown = 5f;
}
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);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Blocked"] = "You cannot pick up {0} here.",
["Owned"] = "This drop belongs to another player."
}, this);
}
private void Init()
{
permission.RegisterPermission(PermBypass, this);
}
private string Msg(string key, string userId = null, params object[] args) => string.Format(lang.GetMessage(key, this, userId), args);
private object OnItemPickup(Item item, BasePlayer player, WorldItem worldItem)
{
if (item?.info == null || player == null || worldItem == null) return null;
if (permission.UserHasPermission(player.UserIDString, PermBypass)) return null;
if (config.BlockedShortnames != null && config.BlockedShortnames.Contains(item.info.shortname))
{
Notify(player, Msg("Blocked", player.UserIDString, item.info.displayName.english));
return true;
}
if (config.ProtectOwnedDrops && worldItem.OwnerID != 0ul && worldItem.OwnerID != player.userID.Get())
{
Notify(player, Msg("Owned", player.UserIDString));
return true;
}
return null;
}
private void Notify(BasePlayer player, string text)
{
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (lastNotice.TryGetValue(player.userID.Get(), out last) && now - last < config.NoticeCooldown) return;
lastNotice[player.userID.Get()] = now;
player.ChatMessage(text);
}
private void Unload()
{
lastNotice.Clear();
}
}
}The plugin keeps a configurable list of blocked shortnames and a switch that forbids picking up world items owned by another player. OnItemPickup reads item.info.shortname, checks it against the list, then compares worldItem.OwnerID to the picker's userID. When either rule matches, the hook returns true (any non-null value works) which cancels the pickup, and the player gets a localized message through lang. The cooldown dictionary stops repeated chat spam from spamming the pickup key. Players with the pickupguard.bypass permission skip all checks, while admins are not special-cased so the permission can be granted deliberately.
Common use cases
Block pickup of specific items
Keep a shortname list in the config, for example loot-only event items, and cancel the pickup so the item stays on the ground until it despawns.
Protect other players' drops
Compare
worldItem.OwnerIDwith the picker so a dropped kit cannot be swiped by another player during a short protection window.Route pickups to a custom reward
Cancel the pickup, read
item.info.itemidanditem.amount, then hand out a scrap or economics reward instead of the raw item.
Pitfalls
Only ground pickups are covered
Looting a box, a corpse or a dropped backpack goes through container moves and does not trigger this hook. Pair it with container-level hooks if those paths must be restricted.
Returning false still cancels
Any non-null return stops the pickup, so a boolean false is treated as a block. Return null explicitly when the pickup should proceed.
Chat spam on repeated RPCs
The client can send the pickup RPC more than once per item, so sending a message on every blocked call floods chat. Use a short per-player cooldown.
Build a plugin with OnItemPickup
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 OnItemPickup
Generate