Skip to content
RustPluginGenerator

OnItemAction

OnItemAction is called when a player client sends an item action command (PlayerInventory.ItemCmd) with an item UID and an action string. Returning a non-null value cancels the original handling of that command.

Signature
object OnItemAction(Item item, string text, BasePlayer player)

Parameters

Hook parameters
ParameterTypeDescription
itemItemThe Item instance resolved from the UID sent by the client. Use item.info.shortname, item.skin or item.parent to identify it. Never null when the hook fires, because the game returns early before calling the hook if the item lookup fails.
textstringThe action string the client sent with the item command, for example a skin-change or clothing/action identifier. Treat it as untrusted client input.
playerBasePlayerThe BasePlayer who issued the command (msg.player). Use it to check permissions or ownership. It can be null when the command does not come from a connected player, so guard before use.

Return value

Returning null lets the command continue through the game's normal checks (ownership, locks, CanMoveItemsFrom). Returning any non-null value makes the patched method return immediately, dropping that item action without further processing. The original method returns void, so the value itself is only used as a cancel signal.

How it works

The hook fires inside PlayerInventory.ItemCmd, which runs when the client sends an ItemCmd network message containing an item UID and a text payload. The game first reads the UID and string, resolves the item with FindItemByUID, and bails out early if the item does not exist. That means item is never null when your hook runs. The original code path that follows validates ownership, locks and CanMoveItemsFrom before acting on the action, so this hook sits before all of those checks.

text is whatever action identifier the client chose to send and player is the sending connection. You can inspect item.info.shortname, item.skin, item.parent and player.UserIDString to decide whether to intervene. Declaring a more specific player type is not useful here since only BasePlayer is passed; narrowing to a subclass would only cause Oxide to skip calls when the sender is not that type.

There is a single injection site, so the hook has one behaviour: a non-null return stops the command from being processed further. Use it for moderation of specific item actions rather than routine per-tick logic.

Example plugin: Block skin actions on non-permitted items

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

namespace Oxide.Plugins
{
    [Info("Item Action Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks item action commands on configured items unless the player has a bypass permission")]
    public class ItemActionGuard : RustPlugin
    {
        private const string PermBypass = "itemactionguard.bypass";

        private PluginConfig config;

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

            [JsonProperty("Log blocked actions")]
            public bool LogBlocked = true;
        }

        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"] = "That action is not allowed on this item."
            }, this);
        }

        private string Msg(string key, string userId = null, params object[] args) =>
            string.Format(lang.GetMessage(key, this, userId), args);

        private void Init()
        {
            permission.RegisterPermission(PermBypass, this);
        }

        private object OnItemAction(Item item, string text, BasePlayer player)
        {
            if (item == null || item.info == null)
                return null;

            if (player == null || player.IsNpc || player.IsAdmin)
                return null;

            if (!config.BlockedShortnames.Contains(item.info.shortname))
                return null;

            if (permission.UserHasPermission(player.UserIDString, PermBypass))
                return null;

            if (config.LogBlocked)
            {
                PrintWarning($"Blocked action '{text}' on {item.info.shortname} for {player.displayName} ({player.UserIDString})");
            }

            player.ChatMessage(Msg("Blocked", player.UserIDString));
            return false;
        }
    }
}

The plugin holds a configurable set of shortnames whose actions should be restricted, plus a permission that exempts staff. In OnItemAction it checks the sender is valid and is not an admin or NPC, then looks at item.info.shortname. If the item is in the protected list and the player lacks the bypass permission, it logs a short warning once and returns a non-null value, which drops the command before the game touches the item. Normal actions on unprotected items return null, so default behaviour is untouched. The config and messages use the standard Oxide patterns, and the permission is registered in Init.

Common use cases

  • Restrict skin changes

    Cancel action strings on expensive items unless the player has a permission, so skins cannot be swapped on locked-down loot.

  • Audit suspicious commands

    Record the shortname, skin and player id for unusual action strings to spot client-side exploit attempts.

  • Event-only item rules

    During an event, block actions on event items for players not on the event team by returning a non-null value.

Pitfalls

  • text is client-controlled

    Do not trust the action string for security decisions. Match against known item shortnames and player permissions instead.

  • player can be null

    The hook receives msg.player, which may be null for non-player senders. Always null-check before reading UserIDString.

  • Cancelling does not remove items

    Returning non-null only stops this command. If you need to remove or modify the item, do it explicitly with item.Remove() or container calls.

Build a plugin with OnItemAction

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

Prompt: Restrict skin changes using the OnItemAction 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 OnItemAction

Generate