OnCupboardClearList
OnCupboardClearList is called when a player clicks the clear button on a tool cupboard or vehicle privilege, before the authorization list is wiped.
object OnCupboardClearList(BuildingPrivlidge privilege, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
privilege | BuildingPrivlidge | The TC or vehicle privilege entity whose authorization list is about to be cleared. Cast to BuildingPrivlidge or VehiclePrivilege to read OwnerID, BuildingBlock, authorizedPlayers or unit contents. |
player | BasePlayer | The player who triggered the clear, i.e. the one holding the clear button in the TC or vehicle UI. Use it to check permissions, teams or identity before allowing the wipe. |
Return value
Return null to let the clear proceed. Return any non-null value to suppress the original code path, which means the authorization list stays intact and no network update is sent for the clear.
How it works
The hook fires inside BuildingPrivlidge.ClearList and VehiclePrivilege.ClearList, which the client invokes over RPC. Both methods first check that the player can interact and can administrate the privilege, then call the hook; only when the hook returns null do they run the actual clear (ClearAuthList for tool cupboards, authorizedPlayers.Clear() for vehicles) and send a network update. Passing a BuildingPrivlidge for the first parameter narrows the hook to tool cupboards only, and passing VehiclePrivilege narrows it to vehicles; declaring BasePlayer for the second keeps both. The clear RPC is separate from authorizing and deauthorizing individual players, so this is the only hook that sees a full wipe. Use it to block or audit mass deauthorization: return a non-null value to cancel, and log to a data file if you want a record of who wiped a base's TC and when. Because it only fires on the explicit UI action, it does not see structure decay or entity kills that take the TC with them.
Other signatures
Oxide also calls OnCupboardClearList from other places in the game with these parameter types. Declare the overload you need, or several:
object OnCupboardClearList(VehiclePrivilege vehiclePrivilege, BasePlayer player)
Example plugin: Lock tool cupboard clears behind a permission and audit them
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("CupboardClearGuard", "RustPluginGenerator", "1.0.0")]
[Description("Requires a permission to clear a tool cupboard list and logs every permitted clear")]
public class CupboardClearGuard : RustPlugin
{
private const string PermUse = "cupboardclearguard.allow";
private PluginConfig config;
private ClearLog log;
private class PluginConfig
{
[JsonProperty("Log clears to data file")]
public bool LogClears { get; set; } = true;
[JsonProperty("Maximum log entries")]
public int MaxEntries { get; set; } = 500;
}
private class ClearLog
{
public List<ClearEntry> Entries { get; set; } = new List<ClearEntry>();
}
private class ClearEntry
{
public string PlayerName { get; set; }
public string PlayerId { get; set; }
public string OwnerId { get; set; }
public string Position { get; set; }
public string Time { get; set; }
}
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>
{
["NoPermission"] = "You need permission to clear this authorization list.",
["LogEmpty"] = "No cupboard clears have been recorded.",
["LogEntry"] = "{0} - {1} cleared {2} at {3}"
}, 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(PermUse, this);
log = Interface.Oxide.DataFileSystem.ReadObject<ClearLog>(Name) ?? new ClearLog();
}
private void Unload()
{
SaveLog();
}
private object OnCupboardClearList(BuildingPrivlidge privilege, BasePlayer player)
{
if (privilege == null || player == null) return null;
if (!permission.UserHasPermission(player.UserIDString, PermUse))
{
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return false;
}
if (config.LogClears)
{
log.Entries.Add(new ClearEntry
{
PlayerName = player.displayName,
PlayerId = player.UserIDString,
OwnerId = privilege.OwnerID.ToString(),
Position = privilege.transform.position.ToString("F0"),
Time = DateTime.UtcNow.ToString("u")
});
while (log.Entries.Count > config.MaxEntries) log.Entries.RemoveAt(0);
SaveLog();
}
return null;
}
private object OnCupboardClearList(VehiclePrivilege vehiclePrivilege, BasePlayer player)
{
if (vehiclePrivilege == null || player == null) return null;
return permission.UserHasPermission(player.UserIDString, PermUse) ? (object)null : false;
}
[ChatCommand("clearlog")]
private void CmdClearLog(BasePlayer player, string command, string[] args)
{
if (player == null || !player.IsAdmin) return;
if (log.Entries.Count == 0)
{
player.ChatMessage(Msg("LogEmpty", player.UserIDString));
return;
}
int start = Math.Max(0, log.Entries.Count - 20);
for (int i = log.Entries.Count - 1; i >= start; i--)
{
var e = log.Entries[i];
player.ChatMessage(Msg("LogEntry", player.UserIDString, e.Time, e.PlayerName, e.OwnerId, e.Position));
}
}
private void SaveLog()
{
Interface.Oxide.DataFileSystem.WriteObject(Name, log);
}
}
}The plugin blocks the TC clear button unless the player holds cupboardclearguard.allow, and returns null for everyone else so owners can still manage their own bases. When a clear is permitted it reads the cupboard's OwnerID, appends a timestamped entry to an in-memory audit list and writes it to oxide/data/CupboardClearLog through the data file system. A chat command lets admins dump the last 20 clear events with the player name, owner id and position, so a raid on a shared base can be traced back. VehiclePrivilege is declared in a second hook method so vehicle clears are subject to the same permission check but skipped from the audit log, since vehicles have no building id.
Common use cases
Require a permission for mass deauthorization
Return a non-null value unless the player holds a registered permission, so ordinary players cannot wipe a shared TC's list by accident or malice.
Audit who cleared a base
Log player id, owner id and position to a data file on each clear, then expose a chat command for admins to review recent wipes on contested bases.
Protect group bases from rogue members
Compare player.currentTeam with the privilege owner's team and block the clear if the player is not the team leader.
Pitfalls
Two call sites, two privilege types
The same hook name is called from BuildingPrivlidge and VehiclePrivilege. If you declare
BuildingPrivlidgein your method signature, Oxide skips the call for vehicles, so handle them in a separate method if vehicles matter.Permission is not authorization
The game already checks CanAdministrate / CanModifyAuth before the hook runs, so the player can already modify the list. Your check adds a rule; it does not replace the vanilla gate.
Non-null returns from both overloads
Returning anything non-null cancels the clear, including an empty string or a bool. Keep the return path explicit and never return a collection just to log it.
Build a plugin with OnCupboardClearList
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 OnCupboardClearList
Generate