OnUserKicked
OnUserKicked is called when a player is kicked from the server, right after the kick is processed but before disconnect handling runs.
void OnUserKicked(IPlayer iplayer, string reason)Parameters
| Parameter | Type | Description |
|---|---|---|
iplayer | IPlayer | The Oxide IPlayer wrapper for the player being kicked. Use iplayer.Id (string), iplayer.Name, iplayer.IsConnected and similar members; the underlying BasePlayer is available through iplayer.Object. |
reason | string | The kick message string passed to the kick (for example the text an admin typed or the reason recorded by the ban/kick system). It can be null or empty if no reason was supplied. |
Return value
The return value is ignored; the kick has already been decided when the hook fires. Returning a value or null has no effect on the player or the disconnect flow.
How it works
This hook is raised by Oxide's RustCore wrapper when a player is kicked, for example via kick <name> from the server console or RCON, an admin plugin, or an anti-cheat system that removes a player. It is not a patched game method; Oxide itself invokes it from the internal OnPlayerKicked callback once the player has been resolved to an IPlayer.
iplayer gives you the kicked player's identity and state while they are still known to the server, so you can read the name, Steam ID, or (through iplayer.Object as BasePlayer) their position, team and inventory. reason is the raw text of the kick and is useful for audit logs, Discord relays or moderation records. Because both are handed to you as strings/objects, no game type narrowing is required; declaring the parameter as IPlayer is the only valid form.
Treat it as a notification: kick actions are usually issued from console or another plugin, so the hook fires on every kick regardless of source. There is no way to cancel the kick from this hook.
Example plugin: Log kicks with reason and Steam ID
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("KickLogger", "RustPluginGenerator", "1.0.0")]
[Description("Logs every player kick with reason and Steam ID and notifies online admins.")]
public class KickLogger : RustPlugin
{
private const string PermView = "kicklogger.view";
private const string DataFile = "KickLogger/history";
private PluginConfig config;
private List<string> history;
private class PluginConfig
{
[JsonProperty("Notify online admins in chat")]
public bool NotifyAdmins = true;
[JsonProperty("Max history entries kept")]
public int MaxHistory = 500;
}
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>
{
["KickNotice"] = "{0} ({1}) was kicked: {2}",
["NoReason"] = "no reason given"
}, 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(PermView, this);
}
private void OnServerInitialized()
{
history = Interface.Oxide.DataFileSystem.ReadObject<List<string>>(DataFile) ?? new List<string>();
}
private void Unload()
{
Interface.Oxide.DataFileSystem.WriteObject(DataFile, history);
}
private void OnUserKicked(IPlayer iplayer, string reason)
{
if (iplayer == null) return;
string cleanReason = string.IsNullOrEmpty(reason) ? Msg("NoReason") : reason;
string line = string.Format("{0:u} | {1} | {2} | {3}", DateTime.UtcNow, iplayer.Id, iplayer.Name, cleanReason);
if (history == null) history = new List<string>();
history.Add(line);
if (history.Count > config.MaxHistory)
history.RemoveRange(0, history.Count - config.MaxHistory);
Interface.Oxide.DataFileSystem.WriteObject(DataFile, history);
if (!config.NotifyAdmins) return;
string notice = Msg("KickNotice", null, iplayer.Name, iplayer.Id, cleanReason);
foreach (BasePlayer admin in BasePlayer.activePlayerList)
{
if (admin == null || admin.IsNpc || !admin.IsConnected) continue;
if (!admin.IsAdmin && !permission.UserHasPermission(admin.UserIDString, PermView)) continue;
admin.ChatMessage(notice);
}
}
}
}The plugin listens for OnUserKicked, reads the kicker's IPlayer and the supplied reason, and writes a formatted line to oxide/data/KickLogger/history.txt through Interface.Oxide.DataFileSystem. It also sends a chat notice to any connected admins so staff are aware of moderation actions in real time. The underlying BasePlayer is obtained with iplayer.Object as BasePlayer (with a null check) so the log can include the current position when available. Data is not kept in memory; each kick is appended with ReadObject-style helpers or by reading and re-writing a simple string list. Messages use the lang system so the notice text can be customised without recompiling.
Common use cases
Moderation audit trail
Record every kick with the player's Steam ID, name, reason and timestamp so staff can review who was removed and why.
Discord or log relay
Forward kick events to an external logging plugin or chat channel so connected admins see moderation activity as it happens.
Anti-abuse follow-up
Track repeat offenders by counting kicks per Steam ID in oxide/data and flag players who keep getting removed for the same reason.
Pitfalls
The kick cannot be cancelled
Returning a value from OnUserKicked does nothing; the player is already being removed. Use CanUserLogin or a command-blocking hook if you need to prevent a kick.
Player state may be partially torn down
The hook fires right after the kick is processed, so loot, mounting or inventory state might already be changing. Do not move items or alter the player from this hook.
Reason can be null or empty
Console and plugin-driven kicks sometimes omit a reason. Always null-check and substitute a default label like 'no reason given' in your logs.
Build a plugin with OnUserKicked
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 OnUserKicked
Generate