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.
object OnPlayerCommand(BasePlayer player, string cmd, string[] args)Parameters
| Parameter | Type | Description |
|---|---|---|
player | BasePlayer | The connected BasePlayer who typed the command. Never null at this point in Oxide's command handling. |
cmd | string | The command name without the leading chat prefix, e.g. 'kit' for '/kit cool'. |
args | string[] | 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
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.callorshopwhile 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
falsestill 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
- How to make a Rust combat block plugin (block commands in combat)Tracks combat with the OnEntityTakeDamage hook and blocks a configurable list of chat commands while a player is in combat, using OnPlayerCommand to cancel them. Players see the remaining seconds in chat.
- How to make a Rust command alias plugin (Oxide chat shortcuts)This plugin maps short chat commands like /h and /k to longer ones such as /home and /kit, defined entirely in its config file, using the OnPlayerCommand hook to intercept and reroute the alias.
- How to make a Rust raid block plugin (block tpr/home after explosives)Places a temporary raid block on attackers and on the owner of a building that takes explosive damage, blocking configured chat commands such as /home and /tpr and printing the remaining time. Uses OnEntityTakeDamage to start the block and OnPlayerCommand to enforce it.
Build a plugin with OnPlayerCommand
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 OnPlayerCommand
Generate