OnItemSkinChange
OnItemSkinChange is called when a player uses a repair bench to change the skin of the item in its slot, before the game validates skin ownership and applies the change.
object OnItemSkinChange(int inventoryId, Item slot, RepairBench repairBench, BasePlayer player)Parameters
| Parameter | Type | Description |
|---|---|---|
inventoryId | int | The skin ID (workshop/inventory skin number) the player is trying to apply. May be 0 for the default skin; use it to map to a permission group when you restrict skins. |
slot | Item | The Item sitting in the repair bench's single input slot. It is the item whose skin would change, so read slot.info.shortname, slot.uid and slot.skin from it. |
repairBench | RepairBench | The RepairBench entity the player is using. Use repairBench.transform.position for range checks or to send effects back to the player. |
player | BasePlayer | The player who triggered the skin change. Check permissions and team membership against player.UserIDString before allowing a restricted skin. |
Return value
Return null (or nothing) to let the game continue: it validates skin ownership and applies the new skin. Return any non-null object to abort the change, leaving the item with its previous skin and sending nothing further to the client.
How it works
The hook fires inside RepairBench.ChangeSkin, which runs when a player confirms a skin change on a repair bench. The game has already read the requested skin ID from the client message and grabbed the item from the bench slot; the hook runs before the ownership check (player.blueprints.CheckSkinOwnership) and before the item's skin is written.
inventoryId is the requested skin, slot is the item being reskinned, repairBench is the bench entity and player is the user. Read slot.info.shortname to know which item type is being changed and compare slot.skin to detect no-op requests.
Returning a non-null value aborts the change, so the most common use is a permission gate: allow only skins the player has unlocked through your own system. There is no reason to filter by argument type here; all four arguments are always supplied by the same call site.
The hook does not fire for workbench skin swaps (that is ItemModSkinSwapper) nor for applying skins to items that are not sitting in a repair bench.
Example plugin: Restrict repair bench skins to a permission
using System.Linq;
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Skin Change Guard", "RustPluginGenerator", "1.0.0")]
[Description("Restricts repair bench skin changes by permission and a skin blacklist.")]
public class SkinChangeGuard : RustPlugin
{
private const string PermUse = "skinchangeguard.use";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Skins that are always blocked")]
public List<int> BlockedSkins = new List<int>();
}
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 are not allowed to change item skins.",
["BlockedSkin"] = "The skin {0} is not available on this server."
}, 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);
}
private object OnItemSkinChange(int inventoryId, Item slot, RepairBench repairBench, BasePlayer player)
{
if (player == null || slot == null || slot.info == null)
return null;
if (inventoryId != 0 && config.BlockedSkins.Contains(inventoryId))
{
player.ChatMessage(Msg("BlockedSkin", player.UserIDString, inventoryId));
return false;
}
if (player.IsAdmin || permission.UserHasPermission(player.UserIDString, PermUse))
return null;
player.ChatMessage(Msg("NoPermission", player.UserIDString));
return false;
}
}
}The plugin blocks every repair bench skin change unless the player holds skinchangeguard.use or is an admin. Allowed players still go through the game's own ownership check, so you cannot hand out skins they do not own through this hook alone. A config list of blocked skin IDs lets admins blacklist specific workshop skins on top of the permission check. Denials are sent as a language message with the requested skin ID, so players understand why the change was rejected. There are no timers or stored data, and the hook returns null for allowed changes to keep the normal game behavior.
Common use cases
Paid skin marketplace integration
Deny the change when the requested skin ID is not in the player's purchase list from your data file, then prompt them to buy it through your shop plugin.
Blacklist broken or exploit skins
Maintain a config list of skin IDs that must not appear on the server and return non-null for those, regardless of ownership.
VIP-only cosmetics
Check a permission or group before allowing premium skins so only donators can reskin their weapons and tools on the bench.
Pitfalls
This is not the only reskin path
Workbenches with a skin swapper use a different code path, so blocking here does not stop all skin changes. Add a separate guard if you need full coverage.
Ownership is still enforced by the game
Returning null does not grant a skin the player does not own; the game's CheckSkinOwnership check runs right after the hook and will reject it.
Avoid chat spam on rapid requests
Players can confirm skin changes repeatedly; rate-limit denial messages or only reply once per bench use to keep chat clean.
Build a plugin with OnItemSkinChange
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 OnItemSkinChange
Generate