OnItemRecycle
OnItemRecycle is called by a Recycler on each think tick for every item slot it is about to recycle, before the game yields scrap and components. Returning a non-null value skips the normal recycling of that item.
object OnItemRecycle(Item slot, Recycler recycler)Parameters
| Parameter | Type | Description |
|---|---|---|
slot | Item | The Item instance the recycler is currently about to process. It is still in its container at this point, so its info.shortname, skin, amount and condition can be inspected before the game rolls the output. |
recycler | Recycler | The Recycler entity performing the work. Use it to read the machine position, owner, or to stop recycling, and to check what else the recycler still has to process. |
Return value
Return null (or do nothing) to let the recycler process the item normally. Return any non-null value to skip that item's recycling for this pass; the item stays in the container and the recycler stops if nothing else is recyclable.
How it works
The hook fires inside Recycler.RecycleThink, once per recyclable slot the machine examines while it is running. Before the call, the game has already filtered the slot through CanBeRecycled, so slot is a valid item that would normally be converted. The call happens before the yield is generated, which means the item is still intact and you can read info.shortname, skin, amount and condition.
Because the recycler passes this as recycler, you can inspect recycler.transform.position, recycler.OwnerID or run recycler.HasRecyclable() inside the hook. Both parameters are always non-null at the call site, but still null-check them defensively.
Declaring Item and Recycler matches the exact injected types. Narrowing to a subtype is not useful here since Item and Recycler have no relevant subclasses. The hook is a filter, not a replacement: it runs every tick per slot, so keep work cheap and never spam logs. The default behavior after a non-null return is that the recycler checks whether it still has anything to process and calls StopRecycling() if not.
Example plugin: Block recycling of skinned and low-condition items
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("Recycle Guard", "RustPluginGenerator", "1.0.0")]
[Description("Blocks recycling of skinned and low-condition items inside the recycler.")]
public class RecycleGuard : RustPlugin
{
private const string PermBypass = "recycleguard.bypass";
private PluginConfig config;
private class PluginConfig
{
[JsonProperty("Block skinned items")]
public bool BlockSkinned { get; set; } = true;
[JsonProperty("Minimum condition fraction (0-1)")]
public float MinConditionFraction { get; set; } = 0.25f;
[JsonProperty("Notify player when blocked")]
public bool Notify { get; set; } = true;
}
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>
{
["BlockedSkin"] = "You cannot recycle {0}: custom skins are protected.",
["BlockedCondition"] = "You cannot recycle {0}: condition is too low."
}, 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(PermBypass, this);
}
private object OnItemRecycle(Item slot, Recycler recycler)
{
if (slot == null || slot.info == null) return null;
if (config == null) return null;
var player = slot.GetOwnerPlayer();
if (player != null && permission.UserHasPermission(player.UserIDString, PermBypass))
return null;
if (config.BlockSkinned && slot.skin != 0)
{
NotifyBlocked(player, "BlockedSkin", slot.info.displayName.english);
return true;
}
if (slot.maxCondition > 0f)
{
float fraction = slot.condition / slot.maxCondition;
if (fraction < config.MinConditionFraction)
{
NotifyBlocked(player, "BlockedCondition", slot.info.displayName.english);
return true;
}
}
return null;
}
private void NotifyBlocked(BasePlayer player, string key, string itemName)
{
if (!config.Notify || player == null || !player.IsConnected) return;
player.ChatMessage(Msg(key, player.UserIDString, itemName));
}
}
}RecycleGuard intercepts OnItemRecycle and refuses to let the machine consume items the server wants preserved. By default it blocks anything with a non-zero skin (valuable event rewards) and items below a configurable condition fraction, so nearly broken gear and custom skins cannot be destroyed by accident. When a slot is blocked the hook returns a non-null value, so the recycler simply moves on. Players holding permission recycleguard.bypass see the item recycled as normal. A short chat reminder appears only when a recycle is actually blocked, and the plugin reads all thresholds from its config file.
Common use cases
Protect high-value or skinned items
Block recycling of items with a specific skin or shortname so event drops and store items cannot be destroyed. Return any non-null value to skip the item.
Refund instead of recycling
Give the player a custom token or currency before returning non-null, so you replace the vanilla scrap yield with a server-specific reward.
Condition gate
Stop near-broken tools or weapons from being recycled so admins keep them for repair workflows, only allowing recycling above a condition threshold.
Pitfalls
Fires once per slot per tick
The hook is called inside
RecycleThink, so it can run many times per second while the recycler is active. Cache lookups and neverPuts/PrintWarninginside the hook body.Skipping does not refund
Returning non-null only prevents the item from being processed. If you want the player compensated you must give them the reward yourself; the game will not run the yield code.
Recycler may stop
After a non-null return the game calls
StopRecycling()whenHasRecyclable()is false, so blocking every item effectively halts the machine. Read the parameter as the machine itself, not a clone.
Build a plugin with OnItemRecycle
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 OnItemRecycle
Generate