OnMessagePlayer
OnMessagePlayer is called by Oxide right before a chat line is sent to a player, both for BasePlayer.ChatMessage calls and for calls routed through the Player.Message helper.
object OnMessagePlayer(string msg, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
msg | string | The chat line about to be delivered to the player. At the BasePlayer.ChatMessage site it is the raw string; at Player.Message it is already formatted with prefix and args. |
player | BasePlayer | The BasePlayer who will receive the message. You can change your behavior per player, permission or team. |
Return value
Returning null lets the message go through untouched. Returning any non-null object stops delivery: at both call sites the original code checks the hook result and returns early instead of issuing chat.add. Return a non-null value only when you intend to suppress the message.
How it works
This hook does not patch a gameplay method directly; Oxide calls it from two places it controls. First, BasePlayer.ChatMessage(string msg) is called when code sends a line to a single player's chat: Oxide fires the hook with the plain message and the target BasePlayer. Second, Player.Message(player, message, prefix, userId, args) formats the text, then fires the hook with the combined prefix and message plus the optional user id. Because the hook sits on the delivery path, it fires for admin tool announcements, plugin chat replies and many other single-recipient messages, not for global broadcasts that never call these two methods.
Use player to scope rules per player (permission group, team, admin status) and msg to inspect or classify the text. The hook name is shared by two different arities, so declaring one argument set only receives those calls. If you declare a third ulong userId parameter, you only catch the Player.Message variant; a two-parameter method catches the ChatMessage variant. Declaring a narrower second parameter does not help here, since the argument is always a BasePlayer.
Other signatures
Oxide also calls OnMessagePlayer from other places in the game with these parameter types. Declare the overload you need, or several:
object OnMessagePlayer(string formatted, BasePlayer player, ulong userId)
Example plugin: Mute chat output for players with a chat silence flag
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Chat Silence", "RustPluginGenerator", "1.0.0")]
[Description("Suppresses chat lines delivered to steam IDs placed on a silence list.")]
public class ChatSilence : RustPlugin
{
private const string PermAdmin = "chatsilence.admin";
private PluginConfig config;
private HashSet<ulong> silenced;
private class PluginConfig
{
[JsonProperty("Save silence list to disk")]
public bool Persist { get; set; } = true;
}
private class SilenceData
{
[JsonProperty("Silenced steam IDs")]
public List<ulong> Ids { get; set; } = new List<ulong>();
}
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(PermAdmin, this);
LoadData();
}
private void LoadData()
{
silenced = new HashSet<ulong>();
if (!config.Persist) return;
var data = Interface.Oxide.DataFileSystem.ReadObject<SilenceData>(Name);
if (data?.Ids == null) return;
foreach (var id in data.Ids) silenced.Add(id);
}
private void SaveData()
{
if (!config.Persist) return;
Interface.Oxide.DataFileSystem.WriteObject(Name, new SilenceData { Ids = new List<ulong>(silenced) });
}
private object OnMessagePlayer(string msg, BasePlayer player)
{
if (player == null || !player.IsConnected) return null;
if (!silenced.Contains(player.userID.Get())) return null;
return true;
}
[ConsoleCommand("chatsilence.toggle")]
private void CmdToggle(ConsoleSystem.Arg arg)
{
if (arg?.Connection != null && !arg.IsAdmin)
{
arg.ReplyWith("This command is server console only.");
return;
}
string raw = arg.GetString(0, string.Empty);
if (!ulong.TryParse(raw, out ulong target))
{
arg.ReplyWith("Usage: chatsilence.toggle <steamid>");
return;
}
bool nowSilenced;
if (silenced.Contains(target))
{
silenced.Remove(target);
nowSilenced = false;
}
else
{
silenced.Add(target);
nowSilenced = true;
}
SaveData();
arg.ReplyWith($"Silenced: {silenced.Count}. {(nowSilenced ? "Added" : "Removed")} {target}.");
}
private void Unload()
{
SaveData();
silenced?.Clear();
}
}
}The plugin keeps an in-memory set of silenced player IDs. An admin console command chatsilence.toggle <steamid> adds or removes an entry and replies in the console. The OnMessagePlayer(string msg, BasePlayer player) method checks whether the recipient is in the set and returns a non-null object when they are, which makes the patched delivery path return before chat.add runs, so the line is never encoded to that client. The data is saved to oxide/data/ChatSilence on unload so the set survives restarts. Returning null for every other player leaves normal chat untouched.
Common use cases
Silence chat for specific players
Track a list of muted steam IDs and return a truthy object so the game skips
chat.addfor that recipient.Route plugin replies into a log
When
msgstarts with a known prefix, write it to your own history file or send it to an in-game admin panel before letting it pass through.Filter profanity per player
Inspect
msgand return non-null to block messages that violate your rules when the recipient belongs to a monitored group.
Pitfalls
Two arities, not one
The
Player.Messagecall supplies three arguments includinguserId. A two-parameter method will not receive those calls, so declare both overloads if you need full coverage.Broadcasts bypass this hook
Global notices that do not go through
BasePlayer.ChatMessageorPlayer.Messagenever trigger the hook, so it is not a complete chat filter.Do not over-block
Returning non-null stops the message silently. Use narrow conditions and a log so admins notice when legitimate messages vanish.
Build a plugin with OnMessagePlayer
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 OnMessagePlayer
Generate