Skip to content
RustPluginGenerator

OnPlayerCommand

OnPlayerCommand is called when a connected player types a chat command (a message starting with the server command prefix and containing a command word), before Oxide and the game resolve it to a chat command or console command.

Signature
object OnPlayerCommand(BasePlayer player, string cmd, string[] args)

Parameters

Hook parameters
ParameterTypeDescription
playerBasePlayerThe connected BasePlayer who typed the command. Never null at this point in Oxide's command handling.
cmdstringThe command name without the leading chat prefix, e.g. 'kit' for '/kit cool'.
argsstring[]Array of whitespace-separated arguments that followed the command; empty array when no arguments were supplied.

Return value

Return null (or omit a return) to let the command continue to Oxide's normal chat and console command handling. Return any non-null object, including true or false, to block the command: Oxide stops processing the message and the player sees no command output.

How it works

The hook fires inside RustCore.TryRunPlayerCommand after the raw chat line is stripped of newlines, trimmed, and parsed into a command name and argument array. It only runs for players whose connection is active; Rust+ app commands take the separate OnApplicationCommand path. Returning non-null blocks the command: Oxide checks the combined result of OnPlayerCommand and OnUserCommand and, if either is non-null, stops processing so the command never reaches [ChatCommand] methods, server console commands, or chat broadcast.

Use cmd for exact-match filtering or allow/deny lists and args for argument-aware rules. Because player is a full BasePlayer you can check permissions, admin status, team, building privileges or location before deciding. The hook fires for every prefixed chat line, so it is hot: avoid logging, disk writes and allocations. Do not confuse it with OnPlayerChat, which fires for plain chat without the prefix.

Example plugin: Block dangerous console commands from non-admins

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

namespace Oxide.Plugins
{
    [Info("Command Guard", "RustPluginGenerator", "1.0.0")]
    [Description("Blocks configured chat commands from players who lack permission or admin status")]
    public class CommandGuard : RustPlugin
    {
        private const string PermBypass = "commandguard.bypass";

        private PluginConfig config;
        private readonly Dictionary<ulong, float> lastNotice = new Dictionary<ulong, float>();

        private class PluginConfig
        {
            [JsonProperty("Blocked commands (no prefix)")]
            public List<string> BlockedCommands = new List<string> { "heli.call", "shop", "trade" };

            [JsonProperty("Admins are exempt")]
            public bool AdminsExempt = true;

            [JsonProperty("Seconds between notices per player")]
            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"] = "The command '{0}' is disabled right now.",
                ["Denied"] = "You do not have permission to use '{0}'."
            }, 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 OnPlayerCommand(BasePlayer player, string cmd, string[] args)
        {
            if (player == null || string.IsNullOrEmpty(cmd) || config.BlockedCommands == null)
                return null;

            if (!config.BlockedCommands.Contains(cmd, StringComparer.OrdinalIgnoreCase))
                return null;

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

            if (config.AdminsExempt && player.IsAdmin)
                return null;

            Notify(player, "Blocked", cmd);
            return true;
        }

        private void Notify(BasePlayer player, string key, string arg)
        {
            float now = UnityEngine.Time.realtimeSinceStartup;
            float last;
            if (lastNotice.TryGetValue(player.userID, out last) && now - last < config.NoticeCooldown)
                return;

            lastNotice[player.userID] = now;
            player.ChatMessage(Msg(key, player.UserIDString, arg));
        }

        private void Unload()
        {
            lastNotice.Clear();
        }
    }
}

The plugin maintains a configurable list of blocked command names and, optionally, limits blocking to non-admins only. When a player uses the prefix and the parsed command matches an entry, the hook returns true, which tells Oxide to abort processing so the underlying chat command or forwarded console command is never executed. A permission (commandguard.bypass) lets trusted moderators past the filter, and admins are bypassed when the configured flag is on. Blocked attempts are throttled per player to one chat notice every few seconds so the guard does not spam chat when someone repeatedly types a blocked command.

Common use cases

  • Disable overloaded commands

    Block commands such as heli.call or shop while a server event is running by returning non-null for those names.

  • Permission gate for prefixed commands

    Only allow a command when the player holds a permission, blocking everyone else with a translated deny message.

  • Command audit and rate limit

    Count uses of a command per player and block attempts past a threshold, keeping the hot hook light by tracking state in a dictionary.

Pitfalls

  • Any non-null return blocks

    Returning false still blocks the command because Oxide only checks whether the result is null, not its value. Always return null when the command should proceed.

  • Fires for every prefixed line

    The hook runs on each chat message starting with the prefix, so avoid PrintToChat, Puts or allocations on the common path. Only react to the specific command names you care about.

  • Rust+ and console are separate paths

    Commands sent through the Rust+ app go to OnApplicationCommand, and server console commands go to OnServerCommand, so OnPlayerCommand will not see them.

Plugin recipes that use OnPlayerCommand

Build a plugin with OnPlayerCommand

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

Prompt: Disable overloaded commands using the OnPlayerCommand 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 OnPlayerCommand

Generate