OnUserNameUpdated
OnUserNameUpdated is called by Oxide when it records a new nickname for a user during permission data updates. It fires after the stored name has already been overwritten.
void OnUserNameUpdated(string playerId, string oldName, string newName)Parameters
| Parameter | Type | Description |
|---|---|---|
playerId | string | The Steam ID of the user as a string, matching the key Oxide uses in its permission data. |
oldName | string | The last nickname Oxide stored for this user before the update (may be null or empty on first sight). |
newName | string | The sanitized new nickname the game reported for the user. |
Return value
The return value is ignored. The method returns void and the injection uses continue behavior, so returning null or anything else does not stop the nickname from being stored. You can only observe the change, not block it.
How it works
This hook is invoked from Permission.UpdateNickname, which Oxide calls when it refreshes the nickname it keeps for a player in its user data. The method reads the previously stored name, sanitizes the incoming name, writes the new value into LastSeenNickname, and then calls the hook. Because the write happens before Interface.CallHook, oldName reflects the previous stored value and the stored data already holds newName by the time your plugin runs.
Use it to track name changes for moderation logs, name history, or to react to players renaming themselves between sessions. playerId is the string form of the Steam ID, so you can look the player up with BasePlayer.FindByID when online. The name has already been sanitized, so it will not contain rich text tags.
You cannot narrow this hook by parameter type: all three parameters are strings, so every user name update reaches your method. Filter inside the method instead, for example by comparing oldName and newName or by checking whether the ID belongs to a known player.
Example plugin: Log player name changes to chat for admins
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Name Change Logger", "RustPluginGenerator", "1.0.0")]
[Description("Records player name changes and notifies permitted admins")]
public class NameChangeLogger : RustPlugin
{
private const string PermNotify = "namechangelogger.notify";
private PluginConfig config;
private StoredData data;
private class PluginConfig
{
[JsonProperty("Notify online admins with permission")]
public bool NotifyAdmins { get; set; } = true;
}
private class StoredData
{
[JsonProperty("Previous names by player id")]
public Dictionary<string, List<string>> PreviousNames { get; set; } = new Dictionary<string, List<string>>();
}
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>
{
["NameChanged"] = "{0} changed name: {1} -> {2}",
["HistoryHeader"] = "Name history for {0}:",
["HistoryEntry"] = "- {0}",
["NoHistory"] = "No stored name history for {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(PermNotify, this);
LoadData();
}
private void LoadData()
{
data = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name) ?? new StoredData();
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, data);
}
private void OnUserNameUpdated(string playerId, string oldName, string newName)
{
if (string.IsNullOrEmpty(playerId) || string.IsNullOrEmpty(newName)) return;
if (oldName == newName) return;
List<string> history;
if (!data.PreviousNames.TryGetValue(playerId, out history))
{
history = new List<string>();
data.PreviousNames[playerId] = history;
}
if (!string.IsNullOrEmpty(oldName) && !history.Contains(oldName))
history.Add(oldName);
if (!config.NotifyAdmins || string.IsNullOrEmpty(oldName)) return;
foreach (var player in BasePlayer.activePlayerList)
{
if (player == null || !permission.UserHasPermission(player.UserIDString, PermNotify)) continue;
player.ChatMessage(Msg("NameChanged", player.UserIDString, playerId, oldName, newName));
}
}
[ChatCommand("name.history")]
private void CmdHistory(BasePlayer player, string command, string[] args)
{
if (player == null) return;
if (!player.IsAdmin && !permission.UserHasPermission(player.UserIDString, PermNotify))
{
player.ChatMessage("You do not have permission to use this command.");
return;
}
if (args == null || args.Length == 0)
{
player.ChatMessage("Usage: /name.history <steamid>");
return;
}
string targetId = args[0];
List<string> history;
if (!data.PreviousNames.TryGetValue(targetId, out history) || history.Count == 0)
{
player.ChatMessage(Msg("NoHistory", player.UserIDString, targetId));
return;
}
player.ChatMessage(Msg("HistoryHeader", player.UserIDString, targetId));
foreach (var name in history)
player.ChatMessage(Msg("HistoryEntry", player.UserIDString, name));
}
}
}The plugin listens for OnUserNameUpdated and compares the old and new names, skipping the first record where the old name is empty. When a genuine change is detected it stores the data and, if any online player holds the namechangelogger.notify permission, sends them a chat line with the player ID and both names. Old values are persisted per Steam ID in oxide/data/NameChangeLogger so admins can review history after a restart through the name.changehistory console command, which prints the stored previous names for a given ID. Recent live changes are also broadcast to permitted players only, keeping the information away from regular players.
Common use cases
Moderation name history
Store every previous nickname per Steam ID so staff can link alts or renamed accounts during reports.
Admin notifications
Notify staff with the notify permission whenever a monitored player changes their display name.
Audit trail
Write name changes into a data file that can be reviewed later without relying on external logging.
Pitfalls
The name is already saved
newNamehas been written to Oxide's user data before the hook fires, so you cannot cancel or alter the stored nickname here.First-sight values
On a player's first record
oldNamecan be empty or matchnewName; skip identical or empty comparisons to avoid noisy logs.Player may be offline
Name updates can arrive for disconnected users, so never assume
BasePlayer.FindByIDreturns a player.
Build a plugin with OnUserNameUpdated
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 OnUserNameUpdated
Generate