CanEquipItem
CanEquipItem is called when the game decides whether an item may be moved into an equip slot (belt or wear slot) on a player inventory. Returning a bool overrides that decision.
object CanEquipItem(PlayerInventory playerInventory, Item item, int targetSlot, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
playerInventory | PlayerInventory | The PlayerInventory instance that is trying to equip the item. This is the inventory whose belt and wear slots are being resolved. |
item | Item | The Item being moved into an equip slot. Check item.info for shortname, flags and category, and item.parent for where it currently sits. |
targetSlot | int | The inventory slot index the item is being placed into. Belt slots are 0-5 and wear slots follow; use it to tell belt equips from clothing equips. |
player | BasePlayer | The BasePlayer that owns the inventory. Null checks are still required because the hook fires from several move paths. |
Return value
Return true to let the item be equipped and false to block it; the game skips its own belt-flag check when you return a bool. Returning null (or any non-bool) leaves the vanilla decision intact.
How it works
The hook fires inside PlayerInventory.CanEquipItem, which the game calls before it accepts an item into a slot the player is equipping to. Every equip attempt runs through here: dragging an item from the main inventory into the belt, pressing a belt hotkey bind to move a weapon or tool into a belt slot, and swapping wearables such as armor or clothing. It is also hit by server-side moves that route through the same inventory logic, so do not assume a human is always the cause.
Use item.info.flags and item.info.category to identify the item, targetSlot to distinguish belt slots from wear slots, and player to apply per-player rules such as permissions or team membership. playerInventory is useful when you need to check what currently occupies the slot.
Because the hook is dispatched by parameter type, declaring BasePlayer player is already as specific as the game gets here; you cannot narrow further to a subclass. Keep the method cheap since equipping happens constantly in combat, and avoid allocations in the common allow path.
Example plugin: Restrict belt weapons behind a permission
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Belt Weapon Lock", "RustPluginGenerator", "1.0.0")]
[Description("Blocks equipping restricted items into belt or wear slots without a permission")]
public class BeltWeaponLock : RustPlugin
{
private const string PermUse = "beltweaponlock.use";
private PluginConfig config;
private readonly Dictionary<string, float> lastNotice = new Dictionary<string, float>();
private class PluginConfig
{
[JsonProperty("Block wear slot equips too")]
public bool BlockWearSlots { get; set; } = false;
[JsonProperty("Blocked item shortnames")]
public List<string> BlockedShortnames { get; set; } = new List<string>
{
"rifle.ak",
"rifle.lr300",
"lmg.m249",
"smg.thompson"
};
}
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"] = "You are not allowed to equip {0}.",
["BlockedNoPerm"] = "You need the '{0}' permission to equip this item."
}, this);
}
private string Msg(string key, string userId = null, params object[] args)
{
return string.Format(lang.GetMessage(key, this, userId), args);
}
private void Init()
{
permission.RegisterPermission(PermUse, this);
}
private object CanEquipItem(PlayerInventory playerInventory, Item item, int targetSlot, BasePlayer player)
{
if (item?.info == null || player == null)
return null;
if (item.info.shortname == null)
return null;
if (!config.BlockedShortnames.Contains(item.info.shortname))
return null;
if (permission.UserHasPermission(player.UserIDString, PermUse))
return null;
NotifyPlayer(player, item);
return false;
}
private void NotifyPlayer(BasePlayer player, Item item)
{
if (!player.IsConnected)
return;
float now = UnityEngine.Time.realtimeSinceStartup;
float last;
if (lastNotice.TryGetValue(player.UserIDString, out last) && now - last < 5f)
return;
lastNotice[player.UserIDString] = now;
string name = item.info.displayName?.english ?? item.info.shortname;
player.ChatMessage(Msg("Blocked", player.UserIDString, name));
}
private void Unload()
{
lastNotice.Clear();
}
}
}The plugin blocks equipping ranged weapons into belt slots for players who lack the beltweaponlock.use permission, which lets admins gate combat gear on progression or VIP servers. In CanEquipItem it first rejects missing data, then reads the config flag deciding whether wear slots also count. It allows everything when the item is not in one of the restricted categories, and otherwise checks the permission, sending a throttled chat message through the language file so players understand why the move failed. Permission is registered in Init, and messages are registered in LoadDefaultMessages.
Common use cases
Gate weapons behind permissions
Block players without a permission from equipping any weapon into belt slots, so progression or donor tiers control combat access.
Ban specific items per slot
Maintain a config list of shortnames that may never be equipped, for example removing an item after a balance change without deleting it from inventories.
Roleplay weapon restrictions
Restrict firearms while allowing melee weapons and tools, keeping PvE or roleplay servers melee focused.
Pitfalls
Returning false strands items
A blocked equip leaves the item where it was, so the player keeps it in the main inventory. If your rule fires on pickup paths, combine it with CanMoveItem or the item may never reach a usable slot.
Not every call has a player
The
playerargument can be null when the inventory logic is reached from internal moves. Always null-check before reading permissions or sending chat.Chat spam on hotkey presses
Players press belt binds rapidly, so each denied attempt can trigger a message. Throttle per player or your chat fills during fights.
Build a plugin with CanEquipItem
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 CanEquipItem
Generate